public static List <string> SearchOU(Utilities.Options.Arguments arguments) { try { List <string> ComputerNames = new List <string>(); DirectoryEntry entry = null; DirectorySearcher mySearcher = null; if (!String.IsNullOrEmpty(arguments.dc) && !String.IsNullOrEmpty(arguments.domain)) { try { string directoryEntry = $"GC://{arguments.dc}/DC={arguments.domain.Replace(".", ",DC=")}"; Console.WriteLine($"[+] Attempting to connect to Global Catalog: {directoryEntry}"); entry = new DirectoryEntry(directoryEntry); mySearcher = new DirectorySearcher(entry); } catch (Exception ex) { Console.WriteLine($"[!] LDAP Error connecting to Global Catalog: {ex.Message.Trim()}"); string directoryEntry = $"LDAP://{arguments.dc}/DC={arguments.domain.Replace(".", ",DC=")}"; Console.WriteLine($"[+] Querying DC without Global Catalog: {directoryEntry}"); entry = new DirectoryEntry(directoryEntry); mySearcher = new DirectorySearcher(entry); } } else { string searchbase = "LDAP://" + arguments.ou;//OU=Domain Controllers,DC=example,DC=local"; entry = new DirectoryEntry(searchbase); mySearcher = new DirectorySearcher(entry); } mySearcher.PropertiesToLoad.Add("dnshostname"); // filter for all enabled computers mySearcher.Filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"); mySearcher.SizeLimit = int.MaxValue; mySearcher.PageSize = int.MaxValue; foreach (SearchResult resEnt in mySearcher.FindAll()) { string ComputerName = resEnt.Properties["dnshostname"][0].ToString(); ComputerNames.Add(ComputerName); } Console.WriteLine("[+] OU Search Results: {0}", ComputerNames.Count().ToString()); mySearcher.Dispose(); entry.Dispose(); return(ComputerNames); } catch (Exception ex) { if (arguments.verbose) { Console.WriteLine("[!] LDAP Error: {0}", ex.Message); } //Environment.Exit(0); return(null); } }
public static void PrintOptions(Utilities.Options.Arguments arguments) { Console.WriteLine("[+] Parsed Arguments:"); Console.WriteLine("\tfilter: none"); if (arguments.filter != null) { Console.WriteLine($"\tfilter: {String.Join(",", arguments.filter)}"); } else { Console.WriteLine($"\tfilter: none"); } Console.WriteLine($"\tldap: {arguments.ldap}"); Console.WriteLine($"\tou: {arguments.ou}"); Console.WriteLine($"\tstealth: {arguments.stealth.ToString()}"); Console.WriteLine($"\tthreads: {arguments.threads.ToString()}"); Console.WriteLine($"\tverbose: {arguments.verbose.ToString()}"); if (String.IsNullOrEmpty(arguments.outfile)) { Console.WriteLine("\toutfile: none"); } else { Console.WriteLine($"\toutfile: {arguments.outfile}"); if (!File.Exists(arguments.outfile)) { try { // Create a file to write to if it doesn't exist using (StreamWriter sw = File.CreateText(arguments.outfile)) { }; Console.WriteLine($"[+] {arguments.outfile} Created"); } catch (Exception ex) { Console.WriteLine("[!] Outfile Error: {0}", ex.Message); Environment.Exit(0); } } else { Console.WriteLine($"[!] {arguments.outfile} already esists. Appending to file"); } } if (arguments.filter != null) { Console.WriteLine("[*] Excluding {0} shares", String.Join(",", arguments.filter)); } if (arguments.verbose) { Console.WriteLine("[*] Including unreadable shares"); } Console.WriteLine("[*] Starting share enumeration with thread limit of {0}", arguments.threads.ToString()); Console.WriteLine("[r] = Readable Share\n[w] = Writeable Share\n[-] = Unauthorized Share (requires /verbose flag)\n[?] = Unchecked Share (requires /stealth flag)\n"); }
public static void GetAllShares(List <string> computers, Utilities.Options.Arguments arguments) { Console.WriteLine("[+] Starting share enumeration against {0} hosts\n", computers.Count); //https://blog.danskingdom.com/limit-the-number-of-c-tasks-that-run-in-parallel/ var threadList = new List <Action>(); foreach (string computer in computers) { threadList.Add(() => GetComputerShares(computer, arguments)); } var options = new ParallelOptions { MaxDegreeOfParallelism = arguments.threads }; Parallel.Invoke(options, threadList.ToArray()); Console.WriteLine("[+] Finished Enumerating Shares"); }
public static void GetComputerShares(string computer, Utilities.Options.Arguments argumetns) { //Error 53 - network path was not found //Error 5 - Access Denied string[] errors = { "ERROR=53", "ERROR=5" }; SHARE_INFO_1[] computerShares = EnumNetShares(computer); if (computerShares.Length > 0) { List <string> readableShares = new List <string>(); List <string> writeableShares = new List <string>(); List <string> unauthorizedShares = new List <string>(); // get current user's identity to compare against ACL of shares WindowsIdentity identity = WindowsIdentity.GetCurrent(); string userSID = identity.User.Value; foreach (SHARE_INFO_1 share in computerShares) // <------------ go to next share -----------+ { // | if ((argumetns.filter != null) && (argumetns.filter.Contains(share.shi1_netname.ToString().ToUpper()))) // | { // | continue; // Skip the remainder of this iteration. --------------------------------+ } //share.shi1_netname returns the error code when caught if (argumetns.stealth && !errors.Contains(share.shi1_netname)) { Console.WriteLine("[?] \\\\{0}\\{1}", computer, share.shi1_netname); continue; //do not perform access checks } try { string path = String.Format("\\\\{0}\\{1}", computer, share.shi1_netname); var files = Directory.GetFiles(path); readableShares.Add(share.shi1_netname); AuthorizationRuleCollection rules = Directory.GetAccessControl(path).GetAccessRules(true, true, typeof(System.Security.Principal.SecurityIdentifier)); foreach (FileSystemAccessRule rule in rules) { //https://stackoverflow.com/questions/130617/how-do-you-check-for-permissions-to-write-to-a-directory-or-file // compare SID of group referenced in ACL to groups the current user is a member of if (rule.IdentityReference.ToString() == userSID || identity.Groups.Contains(rule.IdentityReference)) { // plenty of other FileSystem Rights to look for // https://docs.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.filesystemrights if ((//rule.FileSystemRights.HasFlag(FileSystemRights.CreateFiles) || //rule.FileSystemRights.HasFlag(FileSystemRights.WriteAttributes) || //rule.FileSystemRights.HasFlag(FileSystemRights.WriteData) || //rule.FileSystemRights.HasFlag(FileSystemRights.WriteExtendedAttributes) || //rule.FileSystemRights.HasFlag(FileSystemRights.CreateDirectories) || rule.FileSystemRights.HasFlag(FileSystemRights.Write)) && rule.AccessControlType == AccessControlType.Allow) { writeableShares.Add(share.shi1_netname); break; } } } } catch { //share.shi1_netname returns the error code when caught if (!errors.Contains(share.shi1_netname)) { unauthorizedShares.Add(share.shi1_netname); } } } if (readableShares.Count > 0) { foreach (string share in readableShares) { string output = String.Format("[r] \\\\{0}\\{1}", computer, share); if (!String.IsNullOrEmpty(argumetns.outfile)) { try { WriteToFileThreadSafe(output, argumetns.outfile); } catch (Exception ex) { Console.WriteLine("[!] Outfile Error: {0}", ex.Message); //Environment.Exit(0); } } else { Console.WriteLine(output); } } } if (writeableShares.Count > 0) { foreach (string share in writeableShares) { string output = String.Format("[w] \\\\{0}\\{1}", computer, share); if (!String.IsNullOrEmpty(argumetns.outfile)) { try { WriteToFileThreadSafe(output, argumetns.outfile); } catch (Exception ex) { Console.WriteLine("[!] Outfile Error: {0}", ex.Message); //Environment.Exit(0); } } else { Console.WriteLine(output); } } } if (argumetns.verbose && unauthorizedShares.Count > 0) { foreach (string share in unauthorizedShares) { string output = String.Format("[-] \\\\{0}\\{1}", computer, share); if (!String.IsNullOrEmpty(argumetns.outfile)) { try { WriteToFileThreadSafe(output, argumetns.outfile); } catch (Exception ex) { Console.WriteLine("[!] Outfile Error: {0}", ex.Message); //Environment.Exit(0); } } else { Console.WriteLine(output); } } } } Utilities.Status.currentCount += 1; }
public static List <string> SearchLDAP(Utilities.Options.Arguments arguments) { try { bool searchGlobalCatalog = true; List <string> ComputerNames = new List <string>(); string description = null; string filter = null; //https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx //https://ldapwiki.com/wiki/Active%20Directory%20Computer%20Related%20LDAP%20Query switch (arguments.ldap) { case "all": description = "all enabled computers with \"primary\" group \"Domain Computers\""; filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"); break; case "dc": description = "all enabled Domain Controllers (not read-only DCs)"; filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(userAccountControl:1.2.840.113556.1.4.803:=8192))"); break; case "exclude-dc": description = "all enabled computers that are not Domain Controllers or read-only DCs"; filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(!(userAccountControl:1.2.840.113556.1.4.803:=8192))(!(userAccountControl:1.2.840.113556.1.4.803:=67100867)))"); break; case "servers": searchGlobalCatalog = false; //operatingSystem attribute is not replicated in Global Catalog description = "all enabled servers"; filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(operatingSystem=*server*))"); break; case "servers-exclude-dc": searchGlobalCatalog = false; //operatingSystem attribute is not replicated in Global Catalog description = "all enabled servers excluding Domain Controllers or read-only DCs"; filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2))(operatingSystem=*server*)(!(userAccountControl:1.2.840.113556.1.4.803:=8192))(!(userAccountControl:1.2.840.113556.1.4.803:=67100867)))"); break; default: Console.WriteLine("[!] Invalid LDAP filter: {0}", filter); Utilities.Options.Usage(); //Environment.Exit(0); return(null); } if (searchGlobalCatalog) { try { DirectoryEntry entry = null; DirectorySearcher globalCatalogSearcher = null; if (!String.IsNullOrEmpty(arguments.dc) && !String.IsNullOrEmpty(arguments.domain)) { try { string directoryEntry = $"GC://{arguments.dc}/DC={arguments.domain.Replace(".", ",DC=")}"; Console.WriteLine($"[+] Attempting to connect to Global Catalog: {directoryEntry}"); entry = new DirectoryEntry(directoryEntry); globalCatalogSearcher = new DirectorySearcher(entry); } catch (Exception ex) { Console.WriteLine($"[!] LDAP Error connecting to Global Catalog: {ex.Message.Trim()}"); string directoryEntry = $"LDAP://{arguments.dc}/DC={arguments.domain.Replace(".", ",DC=")}"; Console.WriteLine($"[+] Querying DC without Global Catalog: {directoryEntry}"); entry = new DirectoryEntry(directoryEntry); globalCatalogSearcher = new DirectorySearcher(entry); } } else { Forest currentForest = Forest.GetCurrentForest(); GlobalCatalog globalCatalog = currentForest.FindGlobalCatalog(); globalCatalogSearcher = globalCatalog.GetDirectorySearcher(); } globalCatalogSearcher.PropertiesToLoad.Add("dnshostname"); globalCatalogSearcher.Filter = filter; globalCatalogSearcher.SizeLimit = int.MaxValue; globalCatalogSearcher.PageSize = int.MaxValue; Console.WriteLine("[+] Performing LDAP query against Global Catalog for {0}...", description); Console.WriteLine("[+] This may take some time depending on the size of the environment"); foreach (SearchResult resEnt in globalCatalogSearcher.FindAll()) { //sometimes objects with empty attributes throw errors try { string ComputerName = resEnt.Properties["dnshostname"][0].ToString().ToUpper(); ComputerNames.Add(ComputerName); } catch { /*nothing*/ } } globalCatalogSearcher.Dispose(); } catch (Exception ex) { if (arguments.verbose) { Console.WriteLine("[!] LDAP Error searching Global Catalog: {0}", ex.Message); } } } else { try { DirectoryEntry entry = null; DirectorySearcher mySearcher = null; if (!String.IsNullOrEmpty(arguments.dc) && !String.IsNullOrEmpty(arguments.domain)) { string directoryEntry = $"LDAP://{arguments.dc}/DC={arguments.domain.Replace(".", ",DC=")}"; Console.WriteLine($"[+] Performing LDAP query against {directoryEntry} for {description}..."); Console.WriteLine("[+] This may take some time depending on the size of the environment"); entry = new DirectoryEntry(directoryEntry); mySearcher = new DirectorySearcher(entry); } else { entry = new DirectoryEntry(); mySearcher = new DirectorySearcher(entry); } mySearcher.PropertiesToLoad.Add("dnshostname"); mySearcher.Filter = filter; mySearcher.SizeLimit = int.MaxValue; mySearcher.PageSize = int.MaxValue; Console.WriteLine("[+] Performing LDAP query against the current domain for {0}...", description); Console.WriteLine("[+] This may take some time depending on the size of the environment"); foreach (SearchResult resEnt in mySearcher.FindAll()) { //sometimes objects with empty attributes throw errors try { string ComputerName = resEnt.Properties["dnshostname"][0].ToString().ToUpper(); ComputerNames.Add(ComputerName); } catch { /*nothing*/ } } mySearcher.Dispose(); } catch (Exception ex) { if (arguments.verbose) { Console.WriteLine("[!] LDAP Error: {0}", ex.Message); } } } //localhost returns false positives ComputerNames.RemoveAll(u => u.Contains(System.Environment.MachineName.ToUpper())); Console.WriteLine("[+] LDAP Search Results: {0}", ComputerNames.Count.ToString()); return(ComputerNames); } catch (Exception ex) { if (arguments.verbose) { Console.WriteLine("[!] LDAP Error: {0}", ex.Message); } return(null); } }
public static void GetAllShares(List <string> computers, string userSid, List <string> groupIds, Utilities.Options.Arguments arguments) { Console.WriteLine("[+] Starting share enumeration against {0} hosts\n", computers.Count); var threadList = new List <Action>(); if (string.IsNullOrEmpty(userSid)) { foreach (string computer in computers) { //GetComputerShares(computer, userSid, arguments); threadList.Add(() => GetComputerShares(computer, userSid, groupIds, arguments)); } } else { IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse(arguments.dc), 53); LookupClient lookup = new LookupClient(endpoint); var computerIpList = new List <string>() { }; foreach (var computerName in computers) { IPHostEntry hostEntry = lookup.GetHostEntry(computerName); computerIpList.Add(hostEntry.AddressList[0].ToString()); } UserCredentials credentials = new UserCredentials(arguments.userame.Split('\\')[0], arguments.userame.Split('\\')[1], arguments.password); Impersonation.RunAsUser(credentials, LogonType.NewCredentials, (x) => { foreach (string computer in computerIpList) { //GetComputerShares(computer, userSid, arguments); threadList.Add(() => GetComputerShares(computer, userSid, groupIds, arguments)); } }); } var options = new ParallelOptions { MaxDegreeOfParallelism = arguments.threads }; Parallel.Invoke(options, threadList.ToArray()); Console.WriteLine("[+] Finished Enumerating Shares"); }