Created
March 27, 2026 07:40
-
-
Save andreaskueffel/6d04bdddf3e2df8f1e59e3bc40fa397b to your computer and use it in GitHub Desktop.
Subnet Portscanner for Port 80 as Filebased C# App; run with 'dotnet Port80Scanner.cs 192.168.0.0'
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Net; | |
| using System.Net.Sockets; | |
| using System.Net.NetworkInformation; | |
| using System.Text; | |
| using System.Collections.Concurrent; | |
| using System.Runtime.InteropServices; | |
| // ----------------- MAIN ----------------- | |
| Console.OutputEncoding = Encoding.UTF8; | |
| Console.WriteLine("Starting network scan..."); | |
| // Subnetz ermitteln | |
| string subnet = args.Length > 0 | |
| ? string.Join('.', args[0].Split('.').Take(3)) | |
| : Scanner.GetLocalSubnet(); | |
| Console.WriteLine($"Subnet: {subnet}.0/24"); | |
| var found = new ConcurrentBag<(IPAddress IP, string? Host, string? MAC, string? Server)>(); | |
| var oui = await Scanner.LoadOuiAsync(); | |
| var tasks = Enumerable.Range(1, 254).Select(async i => | |
| { | |
| var ip = IPAddress.Parse($"{subnet}.{i}"); | |
| if (!await Scanner.IsPortOpenAsync(ip)) | |
| return; | |
| found.Add(( | |
| ip, | |
| Scanner.TryResolveHostname(ip), | |
| Scanner.GetMacAddress(ip), | |
| await Scanner.GetHttpServerHeader(ip) | |
| )); | |
| }); | |
| await Task.WhenAll(tasks); | |
| // Ausgabe | |
| Console.WriteLine("\n--- Results ---"); | |
| foreach (var f in found.OrderBy(x => x.IP.ToString())) | |
| { | |
| string vendor = Scanner.LookupVendor(f.MAC, oui); | |
| vendor = vendor.Length > 20 ? vendor[..20] : vendor; | |
| Console.WriteLine( | |
| $"{f.IP,-15} Host: {f.Host ?? "-", -15} " + | |
| $"MAC: {f.MAC ?? "-", -17} {vendor,-20} Server: {f.Server ?? "-"}" | |
| ); | |
| } | |
| Console.WriteLine("\nScan done."); | |
| // ----------------- STATISCHE HILFSKLASSE ----------------- | |
| static class Scanner | |
| { | |
| [DllImport("iphlpapi.dll", ExactSpelling = true)] | |
| private static extern int SendARP(int destIp, int srcIp, byte[] pMacAddr, ref uint phyAddrLen); | |
| public static string? GetMacAddress(IPAddress ip) | |
| { | |
| try | |
| { | |
| byte[] mac = new byte[6]; | |
| uint len = 6; | |
| int r = SendARP(BitConverter.ToInt32(ip.GetAddressBytes(), 0), 0, mac, ref len); | |
| return r == 0 ? BitConverter.ToString(mac, 0, (int)len) : null; | |
| } | |
| catch { return null; } | |
| } | |
| public static async Task<bool> IsPortOpenAsync(IPAddress ip, int timeout = 200) | |
| { | |
| using var client = new TcpClient(); | |
| var task = client.ConnectAsync(ip, 80); | |
| return await Task.WhenAny(task, Task.Delay(timeout)) == task; | |
| } | |
| public static async Task<string?> GetHttpServerHeader(IPAddress ip) | |
| { | |
| try | |
| { | |
| using var handler = new SocketsHttpHandler | |
| { | |
| ConnectTimeout = TimeSpan.FromMilliseconds(300) | |
| }; | |
| using var http = new HttpClient(handler) | |
| { | |
| Timeout = TimeSpan.FromMilliseconds(500) | |
| }; | |
| var resp = await http.SendAsync(new HttpRequestMessage(HttpMethod.Head, $"http://{ip}/")); | |
| return resp.Headers.TryGetValues("Server", out var v) ? string.Join(", ", v) : null; | |
| } | |
| catch { return null; } | |
| } | |
| public static string? TryResolveHostname(IPAddress ip) | |
| { | |
| try { return Dns.GetHostEntry(ip).HostName; } | |
| catch { return null; } | |
| } | |
| public static string LookupVendor(string? mac, Dictionary<string, string> oui) | |
| { | |
| if (string.IsNullOrWhiteSpace(mac)) return "-"; | |
| string prefix = mac.ToUpper().Substring(0, 8); | |
| return oui.TryGetValue(prefix, out var vendor) | |
| ? vendor | |
| : "Unknown Vendor"; | |
| } | |
| public static readonly string OuiUrl = "https://standards-oui.ieee.org/oui/oui.txt"; | |
| public static readonly string OuiCacheFile = "oui.txt"; | |
| public static async Task<Dictionary<string, string>> LoadOuiAsync() | |
| { | |
| if (!File.Exists(OuiCacheFile)) | |
| { | |
| Console.WriteLine("Loading OUI-Data from IEEE …"); | |
| using var http = new HttpClient(); | |
| await File.WriteAllTextAsync(OuiCacheFile, await http.GetStringAsync(OuiUrl)); | |
| } | |
| return File.ReadLines(OuiCacheFile) | |
| .Where(l => l.Contains("(hex)")) | |
| .Select(l => | |
| { | |
| var parts = l.Split("(hex)", StringSplitOptions.RemoveEmptyEntries); | |
| return new | |
| { | |
| Prefix = parts[0].Trim().Replace(" ", "-").ToUpper(), | |
| Vendor = parts[1].Trim() | |
| }; | |
| }) | |
| .GroupBy(x => x.Prefix) | |
| .ToDictionary(g => g.Key, g => g.First().Vendor); | |
| } | |
| public static string GetLocalSubnet() | |
| { | |
| var ipv4 = NetworkInterface.GetAllNetworkInterfaces() | |
| .SelectMany(i => i.GetIPProperties().UnicastAddresses) | |
| .FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork) | |
| ?.Address; | |
| if (ipv4 == null) | |
| throw new Exception("No IPv4 found."); | |
| var b = ipv4.GetAddressBytes(); | |
| return $"{b[0]}.{b[1]}.{b[2]}"; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment