├── .gitignore ├── Program.cs ├── Properties └── AssemblyInfo.cs ├── README.md ├── SharpShares.csproj ├── SharpShares.sln └── app.config /.gitignore: -------------------------------------------------------------------------------- 1 | .vs 2 | *.user 3 | [Dd]ebug/* 4 | [Rr]elease/* 5 | [Bb]in/* 6 | [Oo]bj/* 7 | obj/ 8 | -------------------------------------------------------------------------------- /Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Net; 6 | using System.DirectoryServices; 7 | using System.Security.Principal; 8 | using System.DirectoryServices.ActiveDirectory; 9 | using System.Runtime.InteropServices; 10 | using System.Threading; 11 | 12 | namespace SharpShares 13 | { 14 | class Program 15 | { 16 | public static Semaphore MaxThreads { get; set; } 17 | 18 | [DllImport("Netapi32.dll", SetLastError = true)] 19 | public static extern int NetWkstaGetInfo(string servername, int level, out IntPtr bufptr); 20 | 21 | [DllImport("Netapi32.dll", SetLastError = true)] 22 | static extern int NetApiBufferFree(IntPtr Buffer); 23 | 24 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 25 | private static extern int NetShareEnum( 26 | StringBuilder ServerName, 27 | int level, 28 | ref IntPtr bufPtr, 29 | uint prefmaxlen, 30 | ref int entriesread, 31 | ref int totalentries, 32 | ref int resume_handle 33 | ); 34 | 35 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 36 | public struct WKSTA_INFO_100 37 | { 38 | public int platform_id; 39 | public string computer_name; 40 | public string lan_group; 41 | public int ver_major; 42 | public int ver_minor; 43 | } 44 | 45 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 46 | public struct SHARE_INFO_0 47 | { 48 | public string shi0_netname; 49 | } 50 | 51 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 52 | public struct SHARE_INFO_1 53 | { 54 | public string shi1_netname; 55 | public uint shi1_type; 56 | public string shi1_remark; 57 | public SHARE_INFO_1(string sharename, uint sharetype, string remark) 58 | { 59 | this.shi1_netname = sharename; 60 | this.shi1_type = sharetype; 61 | this.shi1_remark = remark; 62 | } 63 | public override string ToString() 64 | { 65 | return shi1_netname; 66 | } 67 | } 68 | 69 | const uint MAX_PREFERRED_LENGTH = 0xFFFFFFFF; 70 | const int NERR_Success = 0; 71 | 72 | private enum NetError : uint 73 | { 74 | NERR_Success = 0, 75 | NERR_BASE = 2100, 76 | NERR_UnknownDevDir = (NERR_BASE + 16), 77 | NERR_DuplicateShare = (NERR_BASE + 18), 78 | NERR_BufTooSmall = (NERR_BASE + 23), 79 | } 80 | 81 | private enum SHARE_TYPE : uint 82 | { 83 | STYPE_DISKTREE = 0, 84 | STYPE_PRINTQ = 1, 85 | STYPE_DEVICE = 2, 86 | STYPE_IPC = 3, 87 | STYPE_SPECIAL = 0x80000000, 88 | } 89 | 90 | public static SHARE_INFO_1[] EnumNetShares(string Server) 91 | { 92 | List ShareInfos = new List(); 93 | int entriesread = 0; 94 | int totalentries = 0; 95 | int resume_handle = 0; 96 | int nStructSize = Marshal.SizeOf(typeof(SHARE_INFO_1)); 97 | IntPtr bufPtr = IntPtr.Zero; 98 | StringBuilder server = new StringBuilder(Server); 99 | int ret = NetShareEnum(server, 1, ref bufPtr, MAX_PREFERRED_LENGTH, ref entriesread, ref totalentries, ref resume_handle); 100 | if (ret == NERR_Success) 101 | { 102 | IntPtr currentPtr = bufPtr; 103 | for (int i = 0; i < entriesread; i++) 104 | { 105 | SHARE_INFO_1 shi1 = (SHARE_INFO_1)Marshal.PtrToStructure(currentPtr, typeof(SHARE_INFO_1)); 106 | ShareInfos.Add(shi1); 107 | currentPtr += nStructSize; 108 | } 109 | NetApiBufferFree(bufPtr); 110 | return ShareInfos.ToArray(); 111 | } 112 | else 113 | { 114 | ShareInfos.Add(new SHARE_INFO_1("ERROR=" + ret.ToString(), 10, string.Empty)); 115 | return ShareInfos.ToArray(); 116 | } 117 | } 118 | 119 | 120 | 121 | public static List GetDomainControllers() 122 | { 123 | List domainControllers = new List(); 124 | try 125 | { 126 | Domain domain = Domain.GetCurrentDomain(); 127 | foreach (DomainController dc in domain.DomainControllers) 128 | { 129 | domainControllers.Add(dc); 130 | } 131 | } 132 | catch { } 133 | return domainControllers; 134 | } 135 | 136 | public static void GetComputerAddresses(List computers) 137 | { 138 | foreach (string computer in computers) 139 | { 140 | try 141 | { 142 | IPAddress[] ips = System.Net.Dns.GetHostAddresses(computer); 143 | foreach (IPAddress ip in ips) 144 | { 145 | if (!ip.ToString().Contains(":")) 146 | { 147 | Console.WriteLine("{0}: {1}", computer, ip); 148 | } 149 | } 150 | } 151 | catch(Exception ex) 152 | { 153 | //Console.WriteLine("[X] ERROR: {0}", ex.Message); 154 | } 155 | } 156 | } 157 | 158 | public static List GetComputers() 159 | { 160 | List computerNames = new List(); 161 | List dcs = GetDomainControllers(); 162 | if (dcs.Count > 0) 163 | { 164 | try 165 | { 166 | Domain domain = Domain.GetCurrentDomain(); 167 | //domain. 168 | string currentUser = WindowsIdentity.GetCurrent().Name.Split('\\')[1]; 169 | 170 | 171 | using (DirectoryEntry entry = new DirectoryEntry(String.Format("LDAP://{0}", dcs[0]))) 172 | { 173 | using (DirectorySearcher mySearcher = new DirectorySearcher(entry)) 174 | { 175 | mySearcher.Filter = ("(objectClass=computer)"); 176 | 177 | // No size limit, reads all objects 178 | mySearcher.SizeLimit = 0; 179 | 180 | // Read data in pages of 250 objects. Make sure this value is below the limit configured in your AD domain (if there is a limit) 181 | mySearcher.PageSize = 250; 182 | 183 | // Let searcher know which properties are going to be used, and only load those 184 | mySearcher.PropertiesToLoad.Add("name"); 185 | 186 | foreach (SearchResult resEnt in mySearcher.FindAll()) 187 | { 188 | // Note: Properties can contain multiple values. 189 | if (resEnt.Properties["name"].Count > 0) 190 | { 191 | string computerName = (string)resEnt.Properties["name"][0]; 192 | computerNames.Add(computerName); 193 | } 194 | } 195 | } 196 | } 197 | } 198 | catch { } 199 | } 200 | else 201 | { 202 | Console.WriteLine("ERROR: Could not get a list of Domain Controllers."); 203 | } 204 | return computerNames; 205 | } 206 | 207 | public static void GetComputerShares(string computer, bool publicOnly = false) 208 | { 209 | string[] errors = { "ERROR=53", "ERROR=5" }; 210 | SHARE_INFO_1[] computerShares = EnumNetShares(computer); 211 | if (computerShares.Length > 0) 212 | { 213 | List readableShares = new List(); 214 | List unauthorizedShares = new List(); 215 | foreach (SHARE_INFO_1 share in computerShares) 216 | { 217 | try 218 | { 219 | string path = String.Format("\\\\{0}\\{1}", computer, share.shi1_netname); 220 | var files = System.IO.Directory.GetFiles(path); 221 | readableShares.Add(share.shi1_netname); 222 | } 223 | catch 224 | { 225 | if (!errors.Contains(share.shi1_netname)) 226 | { 227 | unauthorizedShares.Add(share.shi1_netname); 228 | } 229 | } 230 | } 231 | if (unauthorizedShares.Count > 0 || readableShares.Count > 0) 232 | { 233 | if (publicOnly) 234 | { 235 | if (readableShares.Count > 0) 236 | { 237 | string output = string.Format("Shares for {0}:\n", computer); 238 | output += "\t[--- Listable Shares ---]\n"; 239 | //Console.WriteLine("Shares for {0}:", computer); 240 | //Console.WriteLine("\t[--- Listable Shares ---]"); 241 | foreach (string share in readableShares) 242 | { 243 | output += string.Format("\t\t{0}\n", share); 244 | } 245 | Console.WriteLine(output); 246 | } 247 | } 248 | else 249 | { 250 | string output = string.Format("Shares for {0}:\n", computer); 251 | if (unauthorizedShares.Count > 0) 252 | { 253 | output += "\t[--- Unreadable Shares ---]\n"; 254 | foreach (string share in unauthorizedShares) 255 | { 256 | output += string.Format("\t\t{0}\n", share); 257 | } 258 | } 259 | if (readableShares.Count > 0) 260 | { 261 | output += "\t[--- Listable Shares ---]\n"; 262 | foreach (string share in readableShares) 263 | { 264 | output += string.Format("\t\t{0}", share); 265 | } 266 | } 267 | Console.WriteLine(output); 268 | } 269 | } 270 | } 271 | } 272 | 273 | public static void GetAllShares(List computers, bool publicOnly = false) 274 | { 275 | List runningThreads = new List(); 276 | foreach(string computer in computers) 277 | { 278 | Thread t = new Thread(() => GetComputerShares(computer, publicOnly)); 279 | t.Start(); 280 | runningThreads.Add(t); 281 | } 282 | foreach(Thread t in runningThreads) 283 | { 284 | t.Join(); 285 | } 286 | } 287 | 288 | static void GetComputerVersions(List computers) 289 | { 290 | foreach(string computer in computers) 291 | { 292 | Console.WriteLine("Comptuer: {0}", computer); 293 | string serverName = String.Format("\\\\{0}", computer); 294 | Console.WriteLine(serverName); 295 | IntPtr buffer; 296 | var ret = NetWkstaGetInfo(serverName, 100, out buffer); 297 | var strut_size = Marshal.SizeOf(typeof(WKSTA_INFO_100)); 298 | Console.WriteLine("Ret is:"); 299 | Console.WriteLine(ret); 300 | if (ret == NERR_Success) 301 | { 302 | var info = (WKSTA_INFO_100)Marshal.PtrToStructure(buffer, typeof(WKSTA_INFO_100)); 303 | if (!string.IsNullOrEmpty(info.computer_name)) 304 | { 305 | Console.WriteLine(info.computer_name); 306 | Console.WriteLine(info.platform_id); 307 | Console.WriteLine(info.ver_major); 308 | Console.WriteLine(info.ver_minor); 309 | Console.WriteLine(info.lan_group); 310 | } 311 | } 312 | } 313 | } 314 | 315 | static void Main(string[] args) 316 | { 317 | var computers = GetComputers(); 318 | Console.WriteLine("[*] Parsed {0} computer objects.", computers.Count); 319 | ThreadPool.SetMaxThreads(10, 10); 320 | if (args.Contains("ips")) 321 | { 322 | GetComputerAddresses(computers); 323 | } 324 | else if (args.Contains("shares")) 325 | { 326 | bool pubOnly = false; 327 | if (args.Contains("--public-only")) 328 | { 329 | pubOnly = true; 330 | } 331 | if (args.Length < 2 || (args.Length == 2 && pubOnly)) 332 | { 333 | 334 | GetAllShares(computers, pubOnly); 335 | } 336 | else if (args[1] == "--public-only") 337 | { 338 | GetAllShares(computers, true); 339 | } 340 | else 341 | { 342 | Console.WriteLine("Attempting to enumerate shares for: {0}", args[1]); 343 | List comps = new List(); 344 | comps.Add(args[1]); 345 | GetAllShares(comps, pubOnly); 346 | } 347 | } 348 | else if (args.Contains("versions")) 349 | { 350 | GetComputerVersions(computers); 351 | } 352 | else 353 | { 354 | Console.WriteLine("Error: Not enough arguments. Please pass \"ips\" or \"shares\"."); 355 | } 356 | } 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SharpShares")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SharpShares")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("fe9fdde5-3f38-4f14-8c64-c3328c215cf2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Sharp Shares 2 | 3 | ## Description 4 | 5 | Quick and dirty binary to list network share information from all machines in the current domain and if they're readable. Can also translate all computer names to ip addresses. 6 | 7 | ## Usage 8 | 9 | `SharpShares.exe ips` - Output computer information in the format of `$HOSTNAME: $IP` 10 | 11 | `SharpShares.exe shares` - Query each computer in the domain for network shares and if they're readable by the current user. 12 | 13 | ## Example 14 | 15 | ``` 16 | > .\SharpShares.exe shares 17 | 18 | Shares for WIN-E9V6E2B5IFM: 19 | [--- Unreadable Shares ---] 20 | IPC 21 | [--- Listable Shares --- ] 22 | ADMIN$ 23 | C$ 24 | NETLOGON 25 | SYSVOL 26 | ``` 27 | 28 | ``` 29 | > .\SharpShares.exe ips 30 | WIN-E9V6E2B5IFM: 192.168.193.208 31 | ``` 32 | -------------------------------------------------------------------------------- /SharpShares.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {FE9FDDE5-3F38-4F14-8C64-C3328C215CF2} 8 | Exe 9 | SharpShares 10 | SharpShares 11 | v4.0 12 | 512 13 | true 14 | 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /SharpShares.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2026 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpShares", "SharpShares.csproj", "{FE9FDDE5-3F38-4F14-8C64-C3328C215CF2}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {FE9FDDE5-3F38-4F14-8C64-C3328C215CF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {FE9FDDE5-3F38-4F14-8C64-C3328C215CF2}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {FE9FDDE5-3F38-4F14-8C64-C3328C215CF2}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {FE9FDDE5-3F38-4F14-8C64-C3328C215CF2}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {99BB7918-7BEA-4DF6-A0F9-3E33E1C5FB91} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------