using System.Collections.Concurrent; using System.Net; using System.Net.NetworkInformation; using Backend.Helper; using Models.Handler; using Models.Model.Backend; namespace Backend.Handler; public class ScanSettings { public int Start; public int End; public int ThreadNumber; public EventWaitHandle? Handle; } public class IpScanner { private readonly ConcurrentQueue _queue; private readonly ConcurrentQueue _discardedQueue; private readonly DbHandler _dbHandler; private bool _stop; private int _timeout; public IpScanner(ConcurrentQueue queue, DbHandler dbHandler, ConcurrentQueue discardedQueue) { _queue = queue; _dbHandler = dbHandler; _discardedQueue = discardedQueue; SetTimeout(128); } public void SetTimeout(int milliseconds) { _timeout = milliseconds; } public WaitHandle[] Start(int threads) { int threadsAmount = 0; if (threads % 2 == 0) { threadsAmount = 256 / threads; } WaitHandle[] waitHandles = new WaitHandle[threads]; for (int i = 0; i < threads; i++) { EventWaitHandle handle = new(false, EventResetMode.ManualReset); ScanSettings scanSettings = new() { Start = threadsAmount * i, End = threadsAmount * i + threadsAmount, ThreadNumber = i, Handle = handle }; waitHandles[i] = handle; Thread f = new (Scan!); f.Start(scanSettings); Console.WriteLine($"Scanner thread ({i}) started"); Thread.Sleep(1000); } return waitHandles; } private void Scan(object obj) { ScanSettings scanSettings = (ScanSettings)obj; ScannerResumeObject resumeObject = new(); resumeObject.ThreadNumber = scanSettings.ThreadNumber; resumeObject.StartRange = scanSettings.Start; resumeObject.EndRange = scanSettings.End; ScannerResumeObject? resumeNow = _dbHandler.GetResumeObject(scanSettings.ThreadNumber); int secondByte = 0; int thirdByte = 0; int fourthByte = 0; if (resumeNow is not null) { scanSettings.Start = resumeNow.FirstByte; scanSettings.End = resumeNow.EndRange; secondByte = resumeNow.SecondByte; thirdByte = resumeNow.ThirdByte; fourthByte = resumeNow.FourthByte; } byte[] buf = []; using Ping ping = new(); for (int i = scanSettings.Start; i < scanSettings.End; i++) { if (i is 0 or 10 or 127 or 256) continue; if (i is >= 224 and <= 239) continue; for (int j = secondByte; j < 256; j++) { if (i == 169 && j == 254) continue; if (i == 192 && j == 168) continue; if (i == 198 && j == 18 || j == 19) continue; if (i == 172 && j is >= 16 and <= 31) continue; for (int k = thirdByte; k < 256; k++) { if (i == 192 && k == 2) continue; if (i == 192 && j == 88 && k == 99) continue; if (_discardedQueue.Count >= 2000) { Console.WriteLine("loooooooooooooooooooooooooooool"); Thread.Sleep(500); } for (int l = fourthByte; l < 256; l++) { if (_stop) { resumeObject.FourthByte = l; break; } string ip = $"{i}.{j}.{k}.{l}"; IPStatus responseCode = IPStatus.Unknown; try { // Sometimes, if the pinger gets a Destination Unreachable Communication administratively prohibited response, the pinger will throw an exception. // https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol?useskin=vector#Control_messages _ = IPAddress.TryParse(ip, out IPAddress? address); if (address is not null) { responseCode = ping.Send(address, _timeout, buf, null).Status; } } catch (Exception e) { Console.WriteLine(e); } if (responseCode != IPStatus.Success) { _discardedQueue.Enqueue(CreateDiscardedQueueItem(ip, (int)responseCode)); continue; } (int, int) ports = TcpClientHelper.CheckPort(ip, 80, 443); if (ports is { Item1: 0, Item2: 0 }) { _discardedQueue.Enqueue(CreateDiscardedQueueItem(ip, (int)responseCode)); continue; } _queue.Enqueue(CreateUnfilteredQueueItem(ip, (int)responseCode, ports)); } if (_stop) { resumeObject.ThirdByte = k; break; } } if (_stop) { resumeObject.SecondByte = j; break; } } if (_stop) { resumeObject.FirstByte = i; break; } //Console.WriteLine($"Thread ({scanSettings.ThreadNumber}) is at index ({i}) out of ({scanSettings.End}). Remaining ({scanSettings.End - i})"); } QueueItem resume = new() { ResumeObject = resumeObject, Operations = Operations.Insert }; _queue.Enqueue(resume); scanSettings.Handle!.Set(); } private static Discarded CreateDiscardedQueueItem(string ip, int responseCode) { Discarded discarded = new() { Ip = ip, ResponseCode = responseCode }; return discarded; } private static QueueItem CreateUnfilteredQueueItem(string ip, int responseCode, (int, int) ports) { Unfiltered unfiltered = new() { Ip = ip, ResponseCode = responseCode, Port1 = ports.Item1, Port2 = ports.Item2, Filtered = 0 }; QueueItem superUnfilteredObject = new() { Unfiltered = unfiltered, Operations = Operations.Insert }; return superUnfilteredObject; } public void Stop() { _stop = true; } }