// Figure out what a port is based off its banner public static string FindUnknownPortInfo(string target, int port) { string postScanActions = ""; // A port I'm not familiar with - Try parse the banner List <string> bannerList = General.MultiBannerGrab(target, port); // Remove empty entries bannerList.RemoveAll(x => x == ""); // And dupes bannerList = bannerList.Distinct().ToList(); string unknownPortResult = ""; // ("Port " + port).Pastel(Color.Green); if (!bannerList.Any()) { unknownPortResult += $"Port {port} - Empty".Pastel(Color.Green); Console.WriteLine(unknownPortResult + Environment.NewLine + "- No Response" + Environment.NewLine); return(""); } foreach (string theBanner in bannerList) { unknownPortResult = ""; // Console.WriteLine("Checking: " + theBanner); // We now have a proper banner if (theBanner.StartsWith("220") && theBanner.Contains("ESMTP")) { unknownPortResult += $"Port {port} - SMTP".Pastel(Color.Green); string smtpInfo = SMTP.GetInfo(target, port); // Can't just parse the banner directly since there could be other useful stuff Console.WriteLine(unknownPortResult + Environment.NewLine + smtpInfo + Environment.NewLine); } // SSH else if (theBanner.Contains("SSH-2.0-OpenSSH") || theBanner == "SSH-2.0-Go") { unknownPortResult += $"Port {port} - SSH".Pastel(Color.Green) + Environment.NewLine; if (theBanner.Contains("\r\nProtocol mismatch.")) { unknownPortResult += Environment.NewLine + "- TCP Protocol Mismatch"; } unknownPortResult += SSH.GetInfo(target, port); Console.WriteLine(unknownPortResult + Environment.NewLine); } // WinRM - HTTP with special stuff else if (theBanner.Contains("Server: Microsoft-HTTPAPI/2.0")) { unknownPortResult += $"Port {port} - WinRM".Pastel(Color.Green); string portData = WinRM.GetInfo(target, port); Console.WriteLine(unknownPortResult + Environment.NewLine + portData + Environment.NewLine); } // Squid - HTTP with different special stuff else if (theBanner.Contains("Server: squid")) { unknownPortResult += $"Port {port} - Squid".Pastel(Color.Green); string portData = Squid.GetInfo(target, port); Console.WriteLine(unknownPortResult + Environment.NewLine + portData + Environment.NewLine); } else if (theBanner == "Reecon - HTTPS") { // Console.WriteLine("Found HTTPS - Enumerating"); string httpsData = HTTPS.GetInfo(target, port); if (httpsData != "") { Console.WriteLine(unknownPortResult += $"Port {port} - HTTPS".Pastel(Color.Green) + Environment.NewLine + httpsData + Environment.NewLine); postScanActions += $"- gobuster dir -u=https://{target}:{port}/ -w ~/wordlists/directory-list-2.3-medium.txt -t 25 -o gobuster-{port}-medium.txt -x.php,.txt" + Environment.NewLine; postScanActions += $"- gobuster dir -u=https://{target}:{port}/ -w ~/wordlists/common.txt -t 25 -o gobuster-{port}-common.txt -x.php,.txt" + Environment.NewLine; } } // Probably a general HTTP or HTTPS web server - Try both else if ( theBanner.Contains("Server: Apache") || // Apache Web Server theBanner.Contains("Server: cloudflare") || // Cloudflare Server theBanner.StartsWith("HTTP/1.1") || theBanner.StartsWith("HTTP/1.0") || theBanner.Contains("Error code explanation: 400 = Bad request syntax or unsupported method.") || // BaseHTTP/0.3 Python/2.7.12 theBanner.Contains("<p>Error code: 400</p>") || // TryHackMe - Task 12 Day 7 theBanner.Contains("<h1>Bad Request (400)</h1>") || theBanner.Trim().StartsWith("<!DOCTYPE html>") // General HTML ) { string httpData = HTTP.GetInfo(target, port); if (httpData != "") { Console.WriteLine(unknownPortResult += $"Port {port} - HTTP".Pastel(Color.Green) + Environment.NewLine + httpData + Environment.NewLine); postScanActions += $"- gobuster dir -u=http://{target}:{port}/ -w ~/wordlists/directory-list-2.3-medium.txt -t 25 -o gobuster-" + port + "-medium.txt -x.php,.txt" + Environment.NewLine; postScanActions += $"- gobuster dir -u=http://{target}:{port}/ -w ~/wordlists/common.txt -t 25 -o gobuster-" + port + "-common.txt -x.php,.txt" + Environment.NewLine; } string httpsData = HTTPS.GetInfo(target, port); if (httpsData != "") { Console.WriteLine(unknownPortResult += $"Port {port} - HTTPS".Pastel(Color.Green) + Environment.NewLine + httpsData + Environment.NewLine); postScanActions += $"- gobuster dir -u=https://{target}:{port}/ -w ~/wordlists/directory-list-2.3-medium.txt -t 25 -o gobuster-{port}-medium.txt -x.php,.txt" + Environment.NewLine; postScanActions += $"- gobuster dir -u=https://{target}:{port}/ -w ~/wordlists/common.txt -t 25 -o gobuster-{port}-common.txt -x.php,.txt" + Environment.NewLine; } break; } else if (theBanner == "-ERR unknown command 'Woof'") // Probably Redis { unknownPortResult += $"Port {port} - Redis".Pastel(Color.Green); string portData = Redis.GetInfo(target, port); Console.WriteLine(unknownPortResult + Environment.NewLine + portData + Environment.NewLine); } else if (theBanner == "+OK Dovecot ready.") { unknownPortResult += $"Port {port} - pop3 (Dovecot)".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += POP3.GetInfo(target); Console.WriteLine(unknownPortResult); } else if (theBanner == "ncacn_http/1.0") { // Woof unknownPortResult += "- Microsoft Windows RPC over HTTP".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += "- Reecon currently lacks Microsoft Windows RPC over HTTP support" + Environment.NewLine; Console.WriteLine(unknownPortResult); } else if (theBanner.StartsWith("AMQP")) { byte[] theBannerBytes = General.GetBytes(theBanner); if (bannerList.Count != 8) { Console.WriteLine("AMQP found with an invalid Banner Byte Count! Bug Reelix"); return(""); } // First 0-3: AMQP // 4-7: Version if (theBannerBytes[4] == 0 && theBannerBytes[5] == 0 && theBannerBytes[6] == 9 && theBannerBytes[7] == 1) { Console.WriteLine("Port " + port + " - AMQP".Pastel(Color.Green) + Environment.NewLine + "- Version 0-9-1" + Environment.NewLine + "- Bug Reelix to finish AMQP decoding..." + Environment.NewLine); // theBanner = General.BannerGrab(ip, port, theBanner); // Need to send the bytes of AMQP0091 // Oh gawd.... // \u0001\0\0\0\0\u0001?\0\n\0\n\0\t\0\0\u0001?\fcapabilitiesF\0\0\0?\u0012publisher_confirmst\u0001\u001aexchange_exchange_bindingst\u0001\nbasic.nackt\u0001\u0016consumer_cancel_notifyt\u0001\u0012connection.blockedt\u0001\u0013consumer_prioritiest\u0001\u001cauthentication_failure_closet\u0001\u0010per_consumer_qost\u0001\u000fdirect_reply_tot\u0001\fcluster_nameS\0\0\0\u0010rabbit@dyplesher\tcopyrightS\0\0\0.Copyright (C) 2007-2018 Pivotal Software, Inc.\vinformationS\0\0\05Licensed under the MPL. See http://www.rabbitmq.com/\bplatformS\0\0\0\u0011Erlang/OTP 22.0.7\aproductS\0\0\0\bRabbitMQ\aversionS\0\0\0\u00053.7.8\0\0\0\u000ePLAIN AMQPLAIN\0\0\0\u0005en_US? // https://svn.nmap.org/nmap/nselib/amqp.lua postScanActions += $"- AMQP is up and nmap knows more: nmap --script amqp-info -p{port} {target}" + Environment.NewLine; } else { Console.WriteLine($"Port {port} - AMQP".Pastel(Color.Green) + Environment.NewLine + "- Unknown AMQP Version: " + (int)theBannerBytes[4] + (int)theBannerBytes[5] + (int)theBannerBytes[6] + (int)theBannerBytes[7] + Environment.NewLine); } } else if (theBanner == "</stream:stream>") { unknownPortResult += $"Port {port} - xmpp".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += "- Client Name: Wildfire XMPP Client" + Environment.NewLine; Console.WriteLine(unknownPortResult); } else if (theBanner.StartsWith("@RSYNCD")) { unknownPortResult += $"Port {port} - Rsync".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += Rsync.GetInfo(target, port); Console.WriteLine(unknownPortResult); } else if (theBanner.Trim().StartsWith("( success ( 2 2 ( ) ( edit-pipeline")) { unknownPortResult += $"Port {port} - SVN (Subversion)".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += "- Bug Reelix to fix this. Ref: Port 3690"; Console.WriteLine(unknownPortResult); } else if (theBanner.Length > 5 && theBanner[0] == 255 && theBanner[1] == 253 && theBanner[2] == 24) { unknownPortResult += $"Port {port} - Telnet".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += Telnet.GetInfo(target, port); Console.WriteLine(unknownPortResult); } } // 47538/tcp open socks-proxy Socks4A // -> [?? _ ?? if (unknownPortResult == "") { // If there are 2 results and 1 "Closed" - Removed the Closed if (bannerList.Count == 2) { if (bannerList.Count(x => x == "Reecon - Closed") == 1) { bannerList.RemoveAll(x => x == "Reecon - Closed"); } } if (bannerList.Count == 1) { string theBanner = bannerList[0]; if (theBanner == "Reecon - Connection reset by peer") { unknownPortResult += $"Port {port} - Reset" + Environment.NewLine; unknownPortResult += "- Connection reset by peer (No Useful response)" + Environment.NewLine; } else if (theBanner == "Reecon - Closed") { unknownPortResult += $"Port {port} - Closed".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += "- Port is closed" + Environment.NewLine; } else { unknownPortResult += $"Port {port} - Unknown".Pastel(Color.Green) + Environment.NewLine; unknownPortResult += "- Unknown Response: -->" + theBanner + "<--" + Environment.NewLine; unknownPortResult += $"- TODO: nmap -sC -sV {target} -p{port}" + Environment.NewLine; } } else { unknownPortResult += $"Port {port} - Unknown (Dumping possible outcomes)".Pastel(Color.Red) + Environment.NewLine; // Truly unknown - Find the best result foreach (string theBanner in bannerList) { if (theBanner == "Reecon - Connection reset by peer") { unknownPortResult += "- Connection reset by peer (No Useful response)" + Environment.NewLine; } else if (theBanner == "Reecon - Closed") { unknownPortResult += "- Port is closed" + Environment.NewLine; } else { unknownPortResult += "- Unknown Response: -->" + theBanner + "<--" + Environment.NewLine; unknownPortResult += $"- TODO: nmap -sC -sV {target} -p{port}" + Environment.NewLine; } } } Console.WriteLine(unknownPortResult); } return(postScanActions); }
static void Main(string[] args) { DateTime startDate = DateTime.Now; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine("Reecon - Version 0.25c ( https://github.com/Reelix/Reecon )"); Console.ForegroundColor = ConsoleColor.White; if (args.Length == 0) { Console.WriteLine("Usage"); Console.WriteLine("-----"); Console.WriteLine("Basic Scan:\tReecon IPHere (Optional: -noping to skip the online check)"); Console.WriteLine("Display IP:\tReecon -ip"); Console.WriteLine("NMap-Load Scan:\tReecon outfile.nmap (Requires -oG on a regular nmap scan)"); Console.WriteLine("Binary Pwn:\tReecon -pwn FileName (Very buggy)"); Console.WriteLine("Searchsploit:\tReecon -searchsploit nameHere (Beta)"); Console.WriteLine("Shell Gen:\tReecon -shell"); Console.WriteLine("SMB Brute:\tReecon -smb-brute (Linux Only)"); Console.WriteLine("WinRM Brute:\tReecon -winrm-brute IP UserList PassList"); Console.WriteLine("LFI Test:\tReecon -lfi (Very buggy)"); Console.WriteLine("Web Info:\tReecon -web url (Very buggy)"); Console.ResetColor(); return; } // Check if it's anything custom if (args.Contains("-ip") || args.Contains("--ip")) { General.GetIP(); Console.ResetColor(); return; } else if (args.Contains("-lfi") || args.Contains("--lfi")) { LFI.Scan(args); Console.ResetColor(); return; } else if (args.Contains("-pwn") || args.Contains("--pwn")) { Pwn.Scan(args); Console.ResetColor(); return; } else if (args.Contains("-searchsploit") || args.Contains("--searchsploit")) { Searchsploit.Search(args); Console.ResetColor(); return; } else if (args.Contains("-shell") || args.Contains("--shell")) { Shell.GetInfo(args); Console.ResetColor(); return; } else if (args.Contains("-smb-brute")) { SMB.SMBBrute(args); Console.ResetColor(); return; } else if (args.Contains("-winrm-brute")) { WinRM.WinRMBrute(args); Console.ResetColor(); return; } else if (args.Contains("-web") || args.Contains("--web")) { Web.GetInfo(args); Console.ResetColor(); return; } else if (args.Contains("-osint") || args.Contains("--osint")) { OSINT.GetInfo(args); Console.ResetColor(); return; } // Check if you should check if the target is up bool mustPing = true; if (args.Contains("-noping") || args.Contains("--noping")) { mustPing = false; args = args.Where(x => !x.Contains("noping")).ToArray(); } // A common typo if (args.Contains("-nopign")) { Console.WriteLine("You typo'd noping"); Console.ResetColor(); return; } // Everything below here has a maximum of 2 args if (args.Length > 2) { Console.WriteLine("You probably typo'd something"); Console.ResetColor(); return; } // Target if (args[0].EndsWith(".nmap")) { string fileName = args[0]; var(Target, Ports) = Nmap.ParseFile(fileName, false); target = Target; if (!Ports.Any()) { Console.WriteLine("Error: Empty file - Bug Reelix!"); } else { portList.AddRange(Ports); } } else { target = args[0]; } if (target.StartsWith("http")) { Console.WriteLine("Cannot do a standard scan on a URL - Try a -web scan"); Console.ResetColor(); return; } // Custom ports if (args.Length == 2) { string portArg = args[1]; try { portList.AddRange(portArg.Split(',').ToList().Select(x => int.Parse(x))); } catch { // Not a list of ports - Probably a name } } // First check if it's actually up if (mustPing) { Console.WriteLine("Checking if target is online..."); bool?isHostOnline = General.IsUp(target); General.ClearPreviousConsoleLine(); if (isHostOnline == null) { Console.WriteLine("Invalid target: " + target); return; } if (!isHostOnline.Value) { Console.WriteLine("Host is not responding to pings :("); Console.WriteLine("If you are sure it's up and are specifying ports, you can use -noping"); return; } } if (portList.Count == 0) { // Scan the target string fileName = Nmap.DefaultScan(args, mustPing); fileName += ".nmap"; // Parse the ports var(Target, Ports) = Nmap.ParseFile(fileName, false); target = Target; portList.AddRange(Ports); } // Everything parsed - Down to the scanning! PortInfo.LoadPortInfo(); // Ports have been defined (Either nmap or custom) if (portList.Count != 0) { Console.Write("Scanning: " + target); Console.Write(" (Port"); if (portList.Count > 1) { Console.Write("s"); } Console.WriteLine(": " + string.Join(",", portList) + ")"); ScanPorts(portList); } else { // All parsing and scans done - But still no ports Console.WriteLine("No open ports found to scan :<"); return; } // Everything done - Now for some helpful info! Console.WriteLine("Finished - Some things you probably want to do: "); if (portList.Count == 0) { // Something broke, or there are only UDP Ports :| Console.WriteLine("- nmap -sC -sV -p- " + target + " -oN nmap.txt"); Console.WriteLine("- nmap -sU " + target + " -oN nmap-UDP.txt"); } else { postScanList.Add($"- Nmap Script+Version Scan: nmap -sC -sV -p{string.Join(",", portList)} {target} -oN nmap.txt" + Environment.NewLine); postScanList.Add($"- Nmap UDP Scan: sudo nmap -sU {target}" + Environment.NewLine); foreach (string item in postScanList) { // They already have newlines in them Console.Write(item); } } DateTime endDate = DateTime.Now; TimeSpan t = endDate - startDate; Console.WriteLine("Done in " + string.Format("{0:0.00}s", t.TotalSeconds) + " - Have fun :)"); Console.ResetColor(); }