├── README.md └── genmap.py /README.md: -------------------------------------------------------------------------------- 1 | # GenMAP 2 | 3 | GenMAP: Automating Nmap Scans with Ease 4 | 5 | A tool to automate Nmap scanning with customizable modes for CTF and Pentest. GenMAP provides an easy interface for running Nmap scans with user-friendly output and real-time progress indicators. 6 | 7 | ## Installation 8 | 9 | 1. Clone the repository: 10 | 11 | ```bash 12 | git clone https://github.com/braijan/genmap.git 13 | ``` 14 | 15 | 2. Navigate to the project directory: 16 | 17 | ```bash 18 | cd genmap 19 | ``` 20 | 21 | 3. Make the script executable: 22 | 23 | ```bash 24 | chmod +x genmap.py 25 | ``` 26 | 27 | ## Usage 28 | 29 | To run the tool, use the following command: 30 | 31 | ```bash 32 | python3 genmap.py 33 | -------------------------------------------------------------------------------- /genmap.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import subprocess 4 | import re 5 | import json 6 | import getpass 7 | from datetime import datetime 8 | from rich.console import Console 9 | from pyfiglet import Figlet 10 | 11 | # Initialize console 12 | console = Console() 13 | sudo_password = None 14 | 15 | # **Timestamped File Naming** 16 | def get_timestamp(): 17 | return datetime.now().strftime("%Y-%m-%d_%H-%M-%S") 18 | 19 | # **Print the Banner** 20 | def print_banner(): 21 | fig = Figlet(font="slant") 22 | banner = fig.renderText("genMAP") 23 | console.print(f"[bold cyan]{banner}[/bold cyan]") 24 | console.print("[bold green]GenMAP: Advanced Network Reconnaissance for Pentesters[/bold green]") 25 | console.print(f"[yellow]Created by: K3strelSec | Version: 3.0.0[/yellow]") 26 | console.print("[bold bright_red]---------------------------------------------------[/bold bright_red]") 27 | console.print("[bold cyan]Key:") 28 | console.print("[red]Red - Open Ports[/red]") 29 | console.print("[blue]Blue - Service Information[/blue]") 30 | console.print("[green]Green - OS Details[/green]") 31 | console.print("[yellow]Yellow - Vulnerabilities[/yellow]") 32 | console.print("[white]White - General Info[/white]") 33 | console.print("[purple]Purple - Active Directory / Domain Info[/purple]") 34 | console.print("") 35 | console.print("[bold bright_magenta]---------------------------------------------------[/bold bright_magenta]") 36 | 37 | # **Colorization Function** 38 | def colorize_output(output): 39 | patterns = { 40 | "open_ports": r"(\d+)/(tcp|udp)\s+open", 41 | "service_info": r"(Service Info:.*|http-server-header:.*|http-title:.*)", 42 | "os_details": r"(OS details|Running|CPE:.*): (.+)", 43 | "vulnerabilities": r"(CVE-\d{4}-\d+|exploit|vuln|potentially vulnerable)", 44 | "active_directory": r"(Active Directory|Domain Controller|Kerberos|SMB|LDAP|FQDN)" 45 | } 46 | for key, pattern in patterns.items(): 47 | color = { 48 | "open_ports": "red", "service_info": "blue", "os_details": "green", 49 | "vulnerabilities": "yellow", "active_directory": "purple" 50 | }[key] 51 | output = re.sub(pattern, lambda x: f"[{color}]{x.group()}[/{color}]", output) 52 | return output 53 | 54 | # **Save Scan Results** 55 | import os 56 | 57 | def save_results(target, output, scan_type): 58 | timestamp = get_timestamp() 59 | 60 | # Create a `scans/` directory if it doesn’t exist 61 | base_dir = "scans" 62 | if not os.path.exists(base_dir): 63 | os.makedirs(base_dir) 64 | 65 | # Create a subdirectory for the target IP 66 | target_dir = os.path.join(base_dir, target) 67 | if not os.path.exists(target_dir): 68 | os.makedirs(target_dir) 69 | 70 | # Save scan results inside the IP-specific directory 71 | filename = os.path.join(target_dir, f"genMAP_{scan_type}_scan_{target}_{timestamp}.txt") 72 | with open(filename, "w") as f: 73 | f.write(output) 74 | 75 | console.print(f"\n[bold cyan]Scan saved to: {filename}[/bold cyan]") 76 | 77 | 78 | # **Scan Menu** 79 | def scan_menu(): 80 | console.print("\n[bold cyan]Select a scan mode:[/bold cyan]") 81 | console.print("[1] Basic TCP Scan") 82 | console.print("[2] Aggressive TCP Scan") 83 | console.print("[3] Silent TCP Scan (Stealth)") 84 | console.print("[4] UDP Scan") 85 | console.print("[5] Vulnerability Scan") 86 | console.print("[6] Full Enumeration (TCP + UDP + Vuln)") 87 | console.print("[7] Custom Nmap Scan") 88 | choice = console.input("\n[bold yellow]Enter your choice: [/bold yellow]").strip() 89 | return choice 90 | 91 | # **Run TCP Scan** 92 | def run_tcp_scan(target, aggressive=False, stealth=False, full_enum=False): 93 | global sudo_password 94 | if not sudo_password: 95 | console.print("\n[bold yellow]Please enter your sudo password for this scan:[/bold yellow]") 96 | sudo_password = getpass.getpass("Sudo Password: ") 97 | 98 | if aggressive: 99 | cmd = ["nmap", "-A", "-T4", "-p-", target] 100 | elif stealth: 101 | cmd = ["nmap", "-sS", "-T2", "-Pn", "-p-", "-f", "--mtu", "16", "--scan-delay", "5s", "--randomize-hosts", target] 102 | else: 103 | cmd = ["nmap", "-sS", "-T4", "-p-", "-O", "-sV", "-sC", target] 104 | 105 | execute_scan(target, cmd, "tcp", full_enum=full_enum) # Pass `full_enum` 106 | 107 | # **Run UDP Scan** 108 | def run_udp_scan(target, full_enum=False): 109 | cmd = ["nmap", "-sU", "--top-ports", "200", "-T4", target] 110 | execute_scan(target, cmd, "udp", full_enum=full_enum) # Pass `full_enum` 111 | 112 | 113 | # **Run Vulnerability Scan** 114 | def run_vuln_scan(target, full_enum=False): 115 | cmd = ["nmap", "-sV", "--script=vuln,vulners,http-enum,smb-enum-shares,rdp-enum-encryption", target] 116 | execute_scan(target, cmd, "vuln", full_enum=full_enum) # Pass `full_enum` 117 | 118 | # **Run Custom Scan** 119 | def run_custom_scan(target, custom_args): 120 | cmd = ["nmap"] + custom_args.split() + [target] 121 | execute_scan(target, cmd, "custom") 122 | 123 | # **Execute Scan, Parse Results, and Provide Exploitation Tips** 124 | def execute_scan(target, cmd, scan_type, full_enum=False): 125 | global sudo_password 126 | if not sudo_password: 127 | console.print("\n[bold yellow]Please enter your sudo password for this scan:[/bold yellow]") 128 | sudo_password = getpass.getpass("Sudo Password: ") 129 | 130 | console.print(f"\n[bold green]Running {scan_type.upper()} Scan: {' '.join(cmd)}[/bold green]") 131 | 132 | process = subprocess.Popen(["sudo", "-S"] + cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True) 133 | process.stdin.write(sudo_password + "\n") 134 | process.stdin.flush() 135 | 136 | output_lines = [] 137 | for line in iter(process.stdout.readline, ''): 138 | output_lines.append(line) 139 | 140 | process.stdout.close() 141 | process.wait() 142 | output = "".join(output_lines) 143 | 144 | console.print(f"\n[bold blue]Raw Data ({scan_type.upper()} Scan Output):[/bold blue]") 145 | console.print(colorize_output(output)) 146 | 147 | save_results(target, output, scan_type) 148 | 149 | # Ensure parsed results are displayed every time 150 | parsed_data = parse_results(output) 151 | 152 | ( 153 | open_ports, vulnerabilities, os_details, device_type, service_info, 154 | active_directory, general_info, smb_info, ssl_info, firewall_info, traceroute_info 155 | ) = parsed_data 156 | 157 | console.print("\n[bold cyan]Parsed Results:[/bold cyan]") 158 | console.print(f"[red]Open Ports:[/red] {', '.join([f'{p[0]}/{p[1]} ({p[2]})' for p in open_ports]) if open_ports else 'None'}") 159 | console.print(f"[green]OS Details:[/green] {os_details}") 160 | console.print(f"[blue]Service Info:[/blue] {', '.join(service_info) if service_info else 'None'}") 161 | console.print(f"[purple]Active Directory:[/purple] {', '.join(active_directory) if active_directory else 'None'}") 162 | console.print(f"[yellow]Vulnerabilities:[/yellow] {', '.join(vulnerabilities) if vulnerabilities else 'None'}") 163 | console.print(f"[white]General Info:[/white] {', '.join(general_info) if general_info else 'None'}") 164 | 165 | if smb_info: 166 | console.print("\n[bold magenta]SMB Security Information:[/bold magenta]") 167 | for key, value in smb_info.items(): 168 | console.print(f"[magenta]{key}:[/magenta] {value}") 169 | 170 | if ssl_info: 171 | console.print("\n[bold cyan]SSL/TLS Information:[/bold cyan]") 172 | for key, value in ssl_info.items(): 173 | console.print(f"[cyan]{key}:[/cyan] {value}") 174 | 175 | if firewall_info: 176 | console.print("\n[bold red]Firewall Detection:[/bold red]") 177 | for info in firewall_info: 178 | console.print(f"[red]{info}[/red]") 179 | 180 | if traceroute_info: 181 | console.print("\n[bold yellow]Traceroute Information:[/bold yellow]") 182 | for hop in traceroute_info: 183 | console.print(f"[yellow]{hop}[/yellow]") 184 | 185 | generate_exploitation_tips(open_ports, vulnerabilities, general_info) 186 | 187 | # If running Full Enumeration, continue with the next scan automatically 188 | if full_enum and scan_type == "tcp": 189 | console.print("\n[bold cyan]TCP Scan Complete. Starting UDP Scan...[/bold cyan]") 190 | run_udp_scan(target, full_enum=True) 191 | elif full_enum and scan_type == "udp": 192 | console.print("\n[bold cyan]UDP Scan Complete. Starting Vulnerability Scan...[/bold cyan]") 193 | run_vuln_scan(target, full_enum=True) 194 | elif full_enum and scan_type == "vuln": 195 | console.print("\n[bold cyan]Full Enumeration Completed![/bold cyan]") 196 | 197 | # Only prompt if NOT in Full Enumeration mode 198 | if not full_enum: 199 | next_step = console.input("\n[bold cyan]Do you want to continue with another scan? (y/n): [/bold cyan]").strip().lower() 200 | if next_step == "y": 201 | new_choice = scan_menu() 202 | handle_scan_choice(new_choice, target) 203 | 204 | 205 | # **Handle Scan Choice** 206 | def handle_scan_choice(choice, target, full_enum=False): 207 | global sudo_password 208 | if not sudo_password: 209 | console.print("\n[bold yellow]Please enter your sudo password for this scan:[/bold yellow]") 210 | sudo_password = getpass.getpass("Sudo Password: ") 211 | 212 | if choice == "1": 213 | run_tcp_scan(target) 214 | elif choice == "2": 215 | run_tcp_scan(target, aggressive=True) 216 | elif choice == "3": 217 | run_tcp_scan(target, stealth=True) 218 | elif choice == "4": 219 | run_udp_scan(target) 220 | elif choice == "5": 221 | run_vuln_scan(target) 222 | elif choice == "6": # Fix Full Enumeration 223 | console.print("\n[bold cyan]Running Full Enumeration: TCP + UDP + Vulnerability Scan[/bold cyan]") 224 | run_tcp_scan(target, full_enum=True) # Pass `full_enum=True` to skip prompts 225 | elif choice == "7": 226 | custom_cmd = console.input("[bold yellow]Enter your custom Nmap command (without 'nmap'): [/bold yellow]").strip() 227 | run_custom_scan(target, custom_cmd) 228 | else: 229 | console.print("[bold red]Invalid choice. Please try again.[/bold red]") 230 | 231 | # **Parse Results** 232 | def parse_results(output): 233 | open_ports = re.findall(r"(\d+)/(tcp|udp)\s+open\s+(\S+)", output) 234 | vulnerabilities = list(set(re.findall(r"CVE-\d{4}-\d+", output))) # Remove duplicates 235 | 236 | # Capture OS details 237 | os_details_match = re.search(r"(OS details|Running): (.+)", output) 238 | os_guess_match = re.search(r"Running \(JUST GUESSING\): (.+)", output) 239 | os_cpe_match = re.search(r"CPE: (cpe:/o:[a-z]+:[a-z_]+)", output) 240 | 241 | if os_details_match: 242 | os_details = os_details_match.group(2) 243 | elif os_guess_match: 244 | os_details = f"Guessed: {os_guess_match.group(1)}" 245 | elif os_cpe_match: 246 | os_details = os_cpe_match.group(1) 247 | else: 248 | os_details = "Unknown OS" 249 | 250 | # Capture Service Info 251 | service_info = list(set(re.findall(r"(Service Info: .+|http-server-header: .+|http-title: .+|OS CPE: .+)", output))) 252 | 253 | # Capture Active Directory-related data 254 | active_directory = list(set(re.findall(r"(Active Directory|Domain Controller|Kerberos|SMB|LDAP|FQDN|NTLM)", output))) 255 | 256 | # Additional general information categories 257 | general_info = [] 258 | indicators = { 259 | "File Exposure": [r"(index of /|directory listing|filetype|file)"], 260 | "Credentials": [r"(password|username|credentials|hash|login|admin)"], 261 | "Sensitive Files": [r"(robots.txt|sitemap.xml|exposed|backup|config|db|.pem|.key)"], 262 | "Internal IPs": [r"(\d+\.\d+\.\d+\.\d+)"], 263 | "Web Tech": [r"(PHP|WordPress|Drupal|Joomla|Apache|Tomcat|Node.js)"], 264 | "Miscellaneous": [r"(Public Key|Certificate|TLS|SSL|DNS|Docker|Kubernetes)"] 265 | } 266 | 267 | for category, patterns in indicators.items(): 268 | for pattern in patterns: 269 | matches = re.findall(pattern, output, re.IGNORECASE) 270 | if matches: 271 | general_info.append(f"{category}: {', '.join(set(matches))}") 272 | 273 | # **Extract SMB Security Information** 274 | smb_info = {} 275 | smb_match = re.findall(r"(smb2-security-mode|smb2-time):\s*(.*)", output, re.IGNORECASE) 276 | for key, value in smb_match: 277 | smb_info[key] = value 278 | 279 | # **Extract SSL/TLS Information** 280 | ssl_info = {} 281 | ssl_match = re.findall(r"(TLSv1\.\d|SSLv\d) enabled", output) 282 | if ssl_match: 283 | ssl_info["Enabled Protocols"] = ", ".join(ssl_match) 284 | 285 | # **Extract Firewall Detection** 286 | firewall_info = [] 287 | firewall_patterns = [ 288 | r"Nmap done: 0 IP addresses", 289 | r"(Host seems down|filtered)", 290 | r"Blocked by firewall" 291 | ] 292 | for pattern in firewall_patterns: 293 | if re.search(pattern, output, re.IGNORECASE): 294 | firewall_info.append(pattern) 295 | 296 | # **Extract Traceroute Info** 297 | traceroute_info = re.findall(r"(\d+\.\d+\.\d+\.\d+)\s+\d+.\d+ ms", output) 298 | 299 | return ( 300 | open_ports, vulnerabilities, os_details, "Unknown Device", service_info, 301 | active_directory, general_info, smb_info, ssl_info, firewall_info, traceroute_info 302 | ) 303 | 304 | # **Fully Expanded attack_methods** 305 | def generate_exploitation_tips(open_ports, vulnerabilities, general_info): 306 | recommendations = [] 307 | 308 | attack_methods = { 309 | 21: "FTP detected. Try `ftp `, anonymous login, brute-force (`hydra`).", 310 | 22: "SSH detected. Try key-based attacks, brute-force (`hydra`, `patator`).", 311 | 23: "Telnet detected. Try weak credentials, sniffing (`tcpdump`), MITM attacks.", 312 | 25: "SMTP detected. Check for Open Relay (`Metasploit smtp_version`).", 313 | 53: "DNS detected. Try zone transfer (`dig axfr @`), enumerate subdomains (`dnsenum`).", 314 | 67: "DHCP detected. Rogue DHCP possible (`dhcpstarv`).", 315 | 69: "TFTP detected. Check for open directory listing (`tftp `).", 316 | 80: "HTTP detected. Run `gobuster`, check for SQL Injection, LFI, RCE (`sqlmap`).", 317 | 110: "POP3 detected. Try brute-force (`hydra`).", 318 | 111: "RPCBind detected. Try `rpcinfo -p `, `showmount -e `.", 319 | 119: "NNTP (Usenet) detected. Try authentication bypass (`telnet 119`).", 320 | 123: "NTP detected. Check for amplification attack (`ntpq -c rv `).", 321 | 135: "MSRPC detected. Use `rpcdump.py` from Impacket.", 322 | 137: "NetBIOS detected. Try `nmblookup -A ` to list NetBIOS names.", 323 | 139: "SMB detected. Check for anonymous login, null sessions (`enum4linux`, `smbclient`).", 324 | 143: "IMAP detected. Try brute-force (`hydra`), inspect emails.", 325 | 161: "SNMP detected. Try `snmpwalk -v1 -c public ` for enumeration.", 326 | 389: "LDAP detected. Try anonymous bind (`ldapsearch -x -h `).", 327 | 443: "HTTPS detected. Look for SSL vulnerabilities (`sslscan`, `testssl.sh`).", 328 | 445: "SMB detected. Test for EternalBlue (`Metasploit ms17_010`), password spray.", 329 | 512: "Rexec detected. Try `rsh `, check `.rhosts` files.", 330 | 513: "Rlogin detected. Try `.rhosts` trust abuse.", 331 | 514: "Rsh detected. Possible remote command execution.", 332 | 873: "RSYNC detected. Check for open directory (`rsync --list-only ::`).", 333 | 902: "VMware detected. Check for guest-to-host escape exploits.", 334 | 1080: "SOCKS proxy detected. Possible open relay attack.", 335 | 1433: "MSSQL detected. Try default credentials (`sa` user), enumerate databases (`nmap --script ms-sql*`).", 336 | 1521: "Oracle DB detected. Try `odat.py` for database attacks.", 337 | 1723: "PPTP VPN detected. Check for MS-CHAPv2 vulnerabilities.", 338 | 2049: "NFS detected. Try `showmount -e ` to list shares.", 339 | 2181: "Zookeeper detected. Try `echo srvr | nc 2181`.", 340 | 2375: "Docker API detected. Check for unauthenticated access (`curl http://:2375/version`).", 341 | 3306: "MySQL detected. Try `mysql -u root -h `, check for weak credentials.", 342 | 3389: "RDP detected. Try brute-force (`xfreerdp`), exploit (`BlueKeep`).", 343 | 3632: "DistCC detected. Try remote command execution (`nmap --script distcc-cve2004-2687`).", 344 | 4444: "Metasploit detected. Possible Meterpreter shell running (`nc -nv 4444`).", 345 | 5000: "Docker Registry detected. Check for open access (`curl -X GET http://:5000/v2/_catalog`).", 346 | 5432: "PostgreSQL detected. Try `psql -h -U postgres`, check for weak passwords.", 347 | 5900: "VNC detected. Try password cracking (`hydra -P rockyou.txt -t 4 -s 5900 vnc`).", 348 | 5985: "WinRM detected. Check for admin access (`evil-winrm -i -u -p `).", 349 | 6379: "Redis detected. Check for unauthenticated access (`redis-cli -h ping`).", 350 | 6667: "IRC detected. Check for open proxy (`nmap --script irc-unrealircd-backdoor`).", 351 | 7001: "WebLogic detected. Check for deserialization vulnerabilities.", 352 | 8000: "Common Web App detected. Run `gobuster`, check for admin panels.", 353 | 8080: "Common Proxy/Web App detected. Test for open proxy abuse.", 354 | 8443: "Alternative HTTPS detected. Look for misconfigurations.", 355 | 8888: "Jupyter Notebook detected. Check for open access (`http://:8888/tree`).", 356 | 9000: "PHP-FPM detected. Possible remote code execution (`CVE-2019-11043`).", 357 | 9200: "Elasticsearch detected. Check for unauthenticated API access (`curl -X GET :9200/_cluster/health`).", 358 | 11211: "Memcached detected. Try amplification attacks (`memcrashed`).", 359 | 27017: "MongoDB detected. Try `mongo --host ` to check for unauthenticated access.", 360 | 50000: "SAP Management Console detected. Check for vulnerabilities (`nmap --script sap* -p 50000 `).", 361 | } 362 | 363 | # Fix: Unpack only the first two values and ignore the service name 364 | for port_tuple in open_ports: 365 | port = int(port_tuple[0]) # Extract only the port number 366 | if port in attack_methods: 367 | recommendations.append(attack_methods[port]) 368 | 369 | # Check for CVE vulnerabilities found in the scan 370 | for vuln in vulnerabilities: 371 | recommendations.append(f"Possible exploit available for `{vuln}`. Check ExploitDB: https://www.exploit-db.com/search?cve={vuln}") 372 | 373 | # Print Exploitation Recommendations 374 | console.print("\n[bold cyan]Exploitation Recommendations:[/bold cyan]") 375 | for rec in recommendations: 376 | console.print(f"[bold yellow]- {rec}[/bold yellow]") 377 | 378 | return recommendations 379 | 380 | # **Main Function** 381 | def main(): 382 | print_banner() 383 | target = console.input("[bold yellow]Enter Target IP or domain: [/bold yellow]").strip() 384 | 385 | if not target: 386 | console.print("[bold red]Error: No target entered![/bold red]") 387 | return 388 | 389 | choice = scan_menu() 390 | handle_scan_choice(choice, target) 391 | 392 | if __name__ == "__main__": 393 | main() 394 | --------------------------------------------------------------------------------