/// <summary> /// Perform new scan on host /// </summary> /// <param name="host"></param> public static void ReScanHost(SMBHost host) { HostShare[] hostShares; List <string> discoveredHostShares; SMBScanResult currentResult; // If the recursive level is not set in the Config class, we use the level used for the first scan if (Config.ScanForNewSharesRecusiveLevel == -1) { Config.ScanForNewSharesRecusiveLevel = host.scanRecursiveLevel; } foreach (SMBScanResult scanResult in host.hostSharesScanResult.Values) { ReScanSMBScanResult(scanResult); } // Check whether the scan will be performed on discovered shares only or try to identify new shares. // The discovery operation includes only the scanned hosts. To add new hosts you should use AppendHosts method. if (Config.ScanForNewShares) { hostShares = GetNetShare.EnumNetShares(host.hostname); if (host.hostSharesScanResult.Count > 0) { discoveredHostShares = host.hostSharesScanResult.Keys.ToList(); foreach (HostShare hostShare in hostShares) { if (!discoveredHostShares.Contains(hostShare.shareInfo.shi1_netname)) { currentResult = new SMBScanResult { shareACL = ShareACLUtils.GetShareACL(hostShare), shareSubDirectories = new Dictionary <string, ScanDirectoryResult>() }; if (IsRecursivelyScannable(currentResult.shareACL.share)) { currentResult.shareSubDirectories = ScanShareDirectory(hostShare.ToString(), Config.ScanForNewSharesRecusiveLevel).shareDirectorySubDirectories; } host.hostSharesScanResult.Add(hostShare.shareInfo.shi1_netname, currentResult); } } } else { host.hostSharesScanResult = ScanHost(host.hostname).hostSharesScanResult; } } }
/// <summary> /// Scan host's SMB shares /// </summary> /// <param name="hostname">Target to scan.</param> /// <returns></returns> public static SMBHost ScanHost(string hostname) { SMBHost result = new SMBHost(); SMBScanResult currentResult; HostShare[] hostShares; IPAddress ip = null; result.scanRecursiveLevel = Config.RecursiveLevel; result.hostname = hostname; try { ip = IPAddress.Parse(hostname); result.ip = ip.ToString(); } catch (FormatException) { if ((Config.TryResolveHostName && !TryResolveHostName(hostname))) { Console.WriteLine("[-][" + DateTime.Now.ToString() + "] Could not resolve " + hostname); return(result); } result.ip = ""; } // Get target's shares try { if (Config.Debug) { Console.WriteLine("[*][" + DateTime.Now.ToString() + "] Getting " + hostname + " shares ..."); } hostShares = GetNetShare.EnumNetShares(hostname); } catch (Exception e) { if (Config.Debug) { Console.WriteLine("[-][" + DateTime.Now.ToString() + "] Error on enumerating " + hostname + " shares (" + e.ToString() + ")."); } return(result); } List <SMBShareACL> sharesACL = ShareACLUtils.GetSharesACL(hostShares); // Iterate over target's shares foreach (SMBShareACL shareACL in sharesACL) { // Create SMBScanResult object for every shareInfo currentResult = new SMBScanResult { shareACL = shareACL, shareSubDirectories = new Dictionary <string, ScanDirectoryResult>() }; // if the shareInfo is not IPC$ or a printer, do a recursive scan on the subdirectories if (IsRecursivelyScannable(currentResult.shareACL.share)) { currentResult.shareSubDirectories = ScanShareDirectory(shareACL.share.ToString(), Config.RecursiveLevel).shareDirectorySubDirectories; } result.hostSharesScanResult.Add(shareACL.share.shareInfo.shi1_netname, currentResult); } return(result); }
/// <summary> /// Perform a multi-thread SMB shares scan on hostnames /// </summary> /// <param name="hostnames"></param> /// <returns></returns> public static Dictionary <string, SMBHost> MTScanHosts(string[] hostnames) { Object resultLock = new Object(); List <Thread> threads = new List <Thread>(); Dictionary <string, SMBHost> results = new Dictionary <string, SMBHost>(); int counter = 1; IPAddress ip; Queue <string> targets = new Queue <string>(); Dictionary <int, int> threadsTryJoinAttemps = new Dictionary <int, int>(); List <string> scannedHosts = new List <string>(); void doScan(string host) { try { if (Config.Debug) { Console.WriteLine("[*][" + DateTime.Now.ToString() + "] Starting thread for " + host); } SMBHost TscanResults = ScanHost(host); lock (resultLock) { results.Add(host, TscanResults); } } catch (Exception e) { Console.WriteLine("[-][" + DateTime.Now.ToString() + "] Failed to scan " + host); if (Config.Debug) { Console.WriteLine("[!][THEAD][Exception] " + e.Message); } } return; } bool TryJoinThread(Thread t) { try { bool joinResult = t.Join(Config.ThreadJoinTimeout); int threadJoinAttempts = 0; if (!joinResult) { if (threadsTryJoinAttemps.TryGetValue(t.ManagedThreadId, out threadJoinAttempts)) { if (threadJoinAttempts > Config.ThreadJoinMaxAttempts) { if (Config.Debug) { Console.WriteLine("Thread " + t.ManagedThreadId.ToString() + " will be asked to abort"); } t.Abort(); return(true); } else { threadsTryJoinAttemps[t.ManagedThreadId] = threadJoinAttempts + 1; } } else { if (Config.Debug) { Console.WriteLine("Creating new entry for the thread " + t.ManagedThreadId.ToString()); } threadsTryJoinAttemps.Add(t.ManagedThreadId, 1); } } return(joinResult); } catch (Exception) { return(false); } } Console.WriteLine("[*][" + DateTime.Now.ToString() + "] Starting mutli-threaded scan ..."); if (hostnames.Length > 0) { foreach (string target in hostnames) { if (Config.Debug) { Console.WriteLine("Scanning host number " + counter.ToString() + " (" + target + ")"); } counter++; try { ip = IPAddress.Parse(target); } catch (FormatException) { if ((Config.TryResolveHostName && !TryResolveHostName(target))) { Console.WriteLine("[-][" + DateTime.Now.ToString() + "] Could not resolve " + target); continue; } } try { if (Config.Debug) { Console.WriteLine("[*][" + DateTime.Now.ToString() + "] Scanning shares of " + target); } while (threads.Count >= Config.MaxThreads) { Console.Write("[*][" + DateTime.Now.ToString() + "] Running threads count : " + threads.Count.ToString() + " \r"); if (Config.Debug) { Console.WriteLine("[*][" + DateTime.Now.ToString() + "] Waiting for a place to create a new thread ..."); } threads.RemoveAll(TryJoinThread); } if (!scannedHosts.Contains(target)) { targets.Enqueue(target); Thread thread = new Thread(() => doScan(targets.Dequeue())) { Name = target, IsBackground = true }; threads.Add(thread); thread.Start(); scannedHosts.Add(target); } } catch (Exception e) { if (Config.Debug) { Console.WriteLine("[-][" + DateTime.Now.ToString() + "] Error on scanning " + target + " : " + e.ToString()); } } } } Console.WriteLine("[*][" + DateTime.Now.ToString() + "] Waiting for the remaining threads ..."); do { Console.Write("[*][" + DateTime.Now.ToString() + "] Remaining threads : " + threads.Count.ToString() + " \r"); threads.RemoveAll(TryJoinThread); } while (threads.Count > 0); return(results); }