Skip to content

Commit 5645032

Browse files
authored
improved LDAP search efficiency
1 parent 6fd009c commit 5645032

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

SharpShares/Program.cs

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ public static List<string> SearchLDAP(string filter, bool verbose)
142142

143143
DirectoryEntry entry = new DirectoryEntry();
144144
DirectorySearcher mySearcher = new DirectorySearcher(entry);
145+
mySearcher.PropertiesToLoad.Add("samaccountname");
145146
string description = null;
146147
//https://social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx
147148
//https://ldapwiki.com/wiki/Active%20Directory%20Computer%20Related%20LDAP%20Query
@@ -176,17 +177,15 @@ public static List<string> SearchLDAP(string filter, bool verbose)
176177

177178
mySearcher.SizeLimit = int.MaxValue;
178179
mySearcher.PageSize = int.MaxValue;
179-
int counter = 0;
180180
foreach (SearchResult resEnt in mySearcher.FindAll())
181181
{
182182
string ComputerName = resEnt.GetDirectoryEntry().Name;
183183
if (ComputerName.StartsWith("CN="))
184184
ComputerName = ComputerName.Remove(0, "CN=".Length);
185185
ComputerNames.Add(ComputerName);
186-
counter += 1;
187186
}
188187
Console.WriteLine("[+] LDAP Search Description: {0}", description);
189-
Console.WriteLine("[+] LDAP Search Results: {0}", counter.ToString());
188+
Console.WriteLine("[+] LDAP Search Results: {0}", ComputerNames.Count.ToString());
190189
mySearcher.Dispose();
191190
entry.Dispose();
192191

@@ -210,6 +209,7 @@ public static List<string> SearchOU(string ou, bool verbose)
210209
string searchbase = "LDAP://" + ou;//OU=Domain Controllers,DC=example,DC=local";
211210
DirectoryEntry entry = new DirectoryEntry(searchbase);
212211
DirectorySearcher mySearcher = new DirectorySearcher(entry);
212+
mySearcher.PropertiesToLoad.Add("samaccountname");
213213
// filter for all enabled computers
214214
mySearcher.Filter = ("(&(objectCategory=computer)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))");
215215
mySearcher.SizeLimit = int.MaxValue;
@@ -240,16 +240,11 @@ public static List<string> SearchOU(string ou, bool verbose)
240240
}
241241
}
242242

243-
public static void GetComputerShares(string computer, bool verbose, bool filter, string outfile)
243+
public static void GetComputerShares(string computer, bool verbose, List<string> filter, bool stealth, string outfile)
244244
{
245+
//Error 53 - network path was not found
246+
//Error 5 - Access Denied
245247
string[] errors = { "ERROR=53", "ERROR=5" };
246-
List<string> exclusions = new List<string>();
247-
if (filter)
248-
{
249-
exclusions.Add("NETLOGON");
250-
exclusions.Add("SYSVOL");
251-
exclusions.Add("PRINT$");
252-
}
253248
SHARE_INFO_1[] computerShares = EnumNetShares(computer);
254249
if (computerShares.Length > 0)
255250
{
@@ -261,10 +256,16 @@ public static void GetComputerShares(string computer, bool verbose, bool filter,
261256
string userSID = identity.User.Value;
262257
foreach (SHARE_INFO_1 share in computerShares)// <-- go to next share --+
263258
{ // |
264-
if (exclusions.Contains(share.shi1_netname.ToString().ToUpper()))// |
259+
if (filter.Contains(share.shi1_netname.ToString().ToUpper())) // |
265260
{ // |
266261
continue; // Skip the remainder of this iteration. -------------+
267262
}
263+
//share.shi1_netname returns the error code when caught
264+
if (stealth && !errors.Contains(share.shi1_netname))
265+
{
266+
Console.WriteLine("[?] \\\\{0}\\{1}", computer, share.shi1_netname);
267+
continue; //do not perform access checks
268+
}
268269
try
269270
{
270271
string path = String.Format("\\\\{0}\\{1}", computer, share.shi1_netname);
@@ -294,6 +295,7 @@ public static void GetComputerShares(string computer, bool verbose, bool filter,
294295
}
295296
catch
296297
{
298+
//share.shi1_netname returns the error code when caught
297299
if (!errors.Contains(share.shi1_netname))
298300
{
299301
unauthorizedShares.Add(share.shi1_netname);
@@ -356,13 +358,13 @@ public static void GetComputerShares(string computer, bool verbose, bool filter,
356358
}
357359
}
358360
}
359-
public static void GetAllShares(List<string> computers, int threads, bool verbose, bool filter, string outfile)
361+
public static void GetAllShares(List<string> computers, int threads, bool verbose, List<string> filter, bool stealth, string outfile)
360362
{
361363
//https://blog.danskingdom.com/limit-the-number-of-c-tasks-that-run-in-parallel/
362364
var threadList = new List<Action>();
363365
foreach (string computer in computers)
364366
{
365-
threadList.Add(() => GetComputerShares(computer, verbose, filter, outfile));
367+
threadList.Add(() => GetComputerShares(computer, verbose, filter, stealth, outfile));
366368
}
367369
var options = new ParallelOptions { MaxDegreeOfParallelism = threads };
368370
Parallel.Invoke(options, threadList.ToArray());
@@ -372,7 +374,7 @@ static Dictionary<string, string[]> ParseArgs(string[] args)
372374
{
373375
Dictionary<string, string[]> result = new Dictionary<string, string[]>();
374376
//these boolean variables aren't passed w/ values. If passed, they are "true"
375-
string[] booleans = new string[] { "/verbose", "/filter" };
377+
string[] booleans = new string[] { "/verbose" };
376378
var argList = new List<string>();
377379
foreach (string arg in args)
378380
{
@@ -400,9 +402,7 @@ static void Usage()
400402
▄█ █▀█ █▀█ █▀▄ █▀▀ ▄█ █▀█ █▀█ █▀▄ ██▄ ▄█
401403
402404
Usage:
403-
SharpShares.exe
404-
or w/ optional arguments:
405-
SharpShares.exe /threads:50 /ldap:servers /ou:""OU=Special Servers,DC=example,DC=local"" /filter /verbose /outfile:C:\path\to\file.txt
405+
SharpShares.exe /threads:50 /ldap:servers /ou:""OU=Special Servers,DC=example,DC=local"" /filter:SYSVOL,NETLOGON,IPC$,PRINT$ /verbose /outfile:C:\path\to\file.txt
406406
407407
Optional Arguments:
408408
/threads - specify maximum number of parallel threads (default=25)
@@ -414,21 +414,24 @@ static void Usage()
414414
:servers-exclude-dc - All enabled servers excluding DCs
415415
/ou - specify LDAP OU to query enabled computer objects from
416416
ex: ""OU=Special Servers,DC=example,DC=local""
417-
/filter - exclude SYSVOL, NETLOGON, and print$ shares
417+
/stealth - list share names without performing read/write access checks
418+
/filter - list of comma-separated shares to exclude from enumeration
419+
recommended: SYSVOL,NETLOGON,IPC$,print$
418420
/outfile - specify file for shares to be appended to instead of printing to std out
419421
/verbose - return unauthorized shares
420422
";
421423
Console.WriteLine(usageString);
422424
}
423-
static void PrintOptions(int threads, string ldapFilter, string ou, bool filter, bool verbose, string outfile)
425+
static void PrintOptions(int threads, string ldapFilter, string ou, List<string> filter, bool stealth, bool verbose, string outfile)
424426
{
425-
Console.WriteLine("[+] Parsed Aguments:");
427+
Console.WriteLine("[+] Parsed Arguments:");
426428
Console.WriteLine("\tthreads: {0}", threads.ToString());
427429
if (String.IsNullOrEmpty(ldapFilter)) { ldapFilter = "all"; }
428430
Console.WriteLine("\tldap: {0}", ldapFilter);
429431
if (String.IsNullOrEmpty(ou)) { ou = "none"; }
430432
Console.WriteLine("\tou: {0}", ou);
431433
Console.WriteLine("\tfilter: {0}", filter.ToString());
434+
Console.WriteLine("\tstealth: {0}", stealth.ToString());
432435
Console.WriteLine("\tverbose: {0}", verbose.ToString());
433436
if (String.IsNullOrEmpty(outfile)) { ldapFilter = "none"; }
434437
Console.WriteLine("\toutfile: {0}", outfile);
@@ -438,10 +441,15 @@ static void Main(string[] args)
438441
{
439442
List<string> hosts = new List<string>();
440443
var parsedArgs = ParseArgs(args);
441-
bool filter = false;
444+
List<string> filter = new List<string>();
442445
if (parsedArgs.ContainsKey("/filter"))
443446
{
444-
filter = Convert.ToBoolean(parsedArgs["/filter"][0]);
447+
filter = parsedArgs["/filter"][0].ToUpper().Split(',').ToList();
448+
}
449+
bool stealth = false;
450+
if (parsedArgs.ContainsKey("/stealth"))
451+
{
452+
stealth = Convert.ToBoolean(parsedArgs["/stealth"][0]);
445453
}
446454
bool verbose = false;
447455
if (parsedArgs.ContainsKey("/verbose"))
@@ -477,13 +485,12 @@ static void Main(string[] args)
477485
Usage();
478486
Environment.Exit(0);
479487
}
480-
PrintOptions(threads, ldapFilter, ou, filter, verbose, outfile);
481488
// if no ldap or ou filter specified, search all enabled computer objects
482489
if (!(parsedArgs.ContainsKey("/ldap")) && !(parsedArgs.ContainsKey("/ou")))
483490
{
484-
ldapFilter = "all";
485-
List<string> ldap = SearchLDAP(ldapFilter, verbose);
486-
hosts = hosts.Concat(ldap).ToList();
491+
Console.WriteLine("[!] Must specify hosts using one of the following arguments: /ldap /ou");
492+
Usage();
493+
Environment.Exit(0);
487494
}
488495
//remove duplicate hosts
489496
hosts = hosts.Distinct().ToList();
@@ -500,12 +507,13 @@ static void Main(string[] args)
500507
Console.WriteLine("[!] {0} already esists. Appending to file", outfile);
501508
}
502509
}
503-
Console.WriteLine("[*] Collected {0} enabled computer objects.", hosts.Count);
504-
if (filter) { Console.WriteLine("[*] Excluding SYSVOL, NETLOGON, and print$ shares"); }
510+
//Console.WriteLine("[*] Collected {0} enabled computer objects.", hosts.Count);
511+
if (filter.Count > 0) { Console.WriteLine("[*] Excluding SYSVOL, NETLOGON, IPC$, and print$ shares"); }
505512
if (verbose) { Console.WriteLine("[*] Including unreadable shares"); }
513+
PrintOptions(threads, ldapFilter, ou, filter, stealth, verbose, outfile);
506514
Console.WriteLine("[*] Starting share enumeration with thread limit of {0}", threads.ToString());
507-
Console.WriteLine("[r] = Readable Share\n[w] = Writeable Share\n[-] = Unauthorized Share (requires /verbose flag)\n");
508-
GetAllShares(hosts, threads, verbose, filter, outfile);
515+
Console.WriteLine("[r] = Readable Share\n[w] = Writeable Share\n[-] = Unauthorized Share (requires /verbose flag)\n[?] = Unchecked Share (requires /stealth flag)\n");
516+
GetAllShares(hosts, threads, verbose, filter, stealth, outfile);
509517
}
510518
}
511519
}

0 commit comments

Comments
 (0)