@@ -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
402404Usage:
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
407407Optional 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 ( "\t threads: {0}" , threads . ToString ( ) ) ;
427429 if ( String . IsNullOrEmpty ( ldapFilter ) ) { ldapFilter = "all" ; }
428430 Console . WriteLine ( "\t ldap: {0}" , ldapFilter ) ;
429431 if ( String . IsNullOrEmpty ( ou ) ) { ou = "none" ; }
430432 Console . WriteLine ( "\t ou: {0}" , ou ) ;
431433 Console . WriteLine ( "\t filter: {0}" , filter . ToString ( ) ) ;
434+ Console . WriteLine ( "\t stealth: {0}" , stealth . ToString ( ) ) ;
432435 Console . WriteLine ( "\t verbose: {0}" , verbose . ToString ( ) ) ;
433436 if ( String . IsNullOrEmpty ( outfile ) ) { ldapFilter = "none" ; }
434437 Console . WriteLine ( "\t outfile: {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