├── LICENSE ├── README.md ├── sharpfiles.cs └── sharpshares.cs /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 fullmetalcache 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SharpFiles 2 | SharpFiles now has two programs for your use: 3 | SharpShares (taken and modified from: https://github.com/djhohnstein/SharpShares) 4 | SharpFiles 5 | 6 | Compile both using csc.exe, such as using the following on a Windows 10 system: 7 | 8 | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:sharpshares.exe sharpshares.cs 9 | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:sharpfiles.exe sharpfiles.cs 10 | 11 | First, run sharpshares.exe 12 | 13 | Usage: sharpshares.exe 14 | 15 | SharpShares will output two files: systems.txt, shares.txt 16 | 17 | The systems.txt contains a list of all systems in the environment. The shares.txt contains a list of all shares that are readable by the current user that ran sharpshares.exe. 18 | 19 | Next, take the shares.txt file and feed it into sharpfiles.exe 20 | 21 | Usage: sharpfiles.exe 22 | 23 | Example: sharpfiles.exe shares.txt 50 filesfound.csv 24 | 25 | Note that the search terms are currently hardcoded in the sharpfiles.cs code. Casing doesn't matter and you don't need wildcards. You will need to recompile the program after you change the search terms but it's pretty quick and easy. 26 | 27 | Please note that, by default, it excludes shares NETLOGON, SYSVOL, and shares with $ in the name. You can change this behavior too by modifying the code. Will make all of these command-line options at some point. 28 | -------------------------------------------------------------------------------- /sharpfiles.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using System.Threading; 6 | 7 | public class RecursiveFileProcessor 8 | { 9 | public static void Main(string[] args) 10 | { 11 | string line; 12 | List shares = new List(); 13 | 14 | string sharesFile = args[0]; 15 | int maxThreads = Int32.Parse(args[1]); 16 | string outFile = args[2]; 17 | 18 | System.IO.StreamReader file = 19 | new System.IO.StreamReader(args[0]); 20 | while((line = file.ReadLine()) != null) 21 | { 22 | line = line.Split('\t')[0].Trim(); 23 | if(!line.Contains("$") && !line.Contains("NETLOGON") && ! line.Contains("SYSVOL")) 24 | { 25 | shares.Add(line); 26 | } 27 | } 28 | 29 | file.Close(); 30 | 31 | FileSearcher fSearcher = new FileSearcher(maxThreads, outFile); 32 | fSearcher.ProcessShares(shares); 33 | } 34 | } 35 | 36 | public class FileSearcher 37 | { 38 | private readonly Object _CountLock = new Object(); 39 | private readonly Object _ListLock = new Object(); 40 | 41 | private int _ThreadCount; 42 | private int _MaxThreads; 43 | private string _OutputFile; 44 | 45 | private string[] terms = new string[] {".iso", ".vmdk", ".wim", "unattend", "web.config"}; 46 | 47 | private List _FilesFound = new List(); 48 | 49 | public FileSearcher(int maxThreads, string outputFile) 50 | { 51 | _ThreadCount = 0; 52 | _MaxThreads = maxThreads; 53 | _OutputFile = outputFile; 54 | } 55 | 56 | private Thread StartThread(string path) 57 | { 58 | Thread t = new Thread(() => ProcessShare( path )); 59 | t.Start(); 60 | return t; 61 | } 62 | 63 | public void ProcessShares(List shares) 64 | { 65 | int counter = 0; 66 | foreach(string path in shares) 67 | { 68 | try 69 | { 70 | while(true) 71 | { 72 | lock(_CountLock) 73 | { 74 | if(_ThreadCount < _MaxThreads) 75 | { 76 | _ThreadCount++; 77 | break; 78 | } 79 | } 80 | 81 | Thread.Sleep(1000); 82 | } 83 | 84 | StartThread(path); 85 | } 86 | catch 87 | { 88 | continue; 89 | } 90 | 91 | counter++; 92 | Console.WriteLine(String.Format("Processed : {0}", path)); 93 | Console.WriteLine(String.Format("{0} of {1} Directories", counter, shares.Count)); 94 | } 95 | } 96 | 97 | private void ProcessShare(string path) 98 | { 99 | Queue _Dirs = new Queue(); 100 | 101 | _Dirs.Enqueue( path ); 102 | 103 | while( 0 < _Dirs.Count ) 104 | { 105 | string currDir = _Dirs.Dequeue(); 106 | ProcessDirectory(currDir, _Dirs); 107 | } 108 | lock(_CountLock) 109 | { 110 | _ThreadCount--; 111 | } 112 | } 113 | 114 | public void ProcessDirectory(string targetDirectory, Queue _Dirs) 115 | { 116 | // Process the list of files found in the directory. 117 | try 118 | { 119 | string [] fileEntries = Directory.GetFiles(targetDirectory); 120 | foreach(string fileName in fileEntries) 121 | ProcessFile(fileName); 122 | } 123 | catch{} 124 | 125 | // Recurse into subdirectories of this directory. 126 | try 127 | { 128 | string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory); 129 | foreach(string subdirectory in subdirectoryEntries) 130 | _Dirs.Enqueue(subdirectory); 131 | } 132 | catch{} 133 | } 134 | 135 | public void ProcessFile(string path) 136 | { 137 | string[] filesplit = path.Split('\\'); 138 | string file = filesplit[filesplit.Length - 1]; 139 | 140 | foreach( string term in terms) 141 | { 142 | if( file.ToLower().Contains(term.ToLower()) ) 143 | { 144 | lock(_ListLock) 145 | { 146 | _FilesFound.Add(path); 147 | 148 | using (System.IO.StreamWriter outFile = 149 | new System.IO.StreamWriter(_OutputFile, true)) 150 | { 151 | outFile.WriteLine(path); 152 | } 153 | } 154 | 155 | break; 156 | } 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /sharpshares.cs: -------------------------------------------------------------------------------- 1 | //Taken from here and modified: https://github.com/djhohnstein/SharpShares 2 | using System; 3 | using System.Collections.Generic; 4 | using System.DirectoryServices; 5 | using System.DirectoryServices.ActiveDirectory; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Net; 9 | using System.Runtime.InteropServices; 10 | using System.Security.Principal; 11 | using System.Text; 12 | using System.Threading; 13 | 14 | namespace SharpShares 15 | { 16 | class Program 17 | { 18 | private static Object thisLock = new Object(); 19 | 20 | public static Semaphore MaxThreads { get; set; } 21 | 22 | [DllImport("Netapi32.dll", SetLastError = true)] 23 | public static extern int NetWkstaGetInfo(string servername, int level, out IntPtr bufptr); 24 | 25 | [DllImport("Netapi32.dll", SetLastError = true)] 26 | static extern int NetApiBufferFree(IntPtr Buffer); 27 | 28 | [DllImport("Netapi32.dll", CharSet = CharSet.Unicode)] 29 | private static extern int NetShareEnum( 30 | StringBuilder ServerName, 31 | int level, 32 | ref IntPtr bufPtr, 33 | uint prefmaxlen, 34 | ref int entriesread, 35 | ref int totalentries, 36 | ref int resume_handle 37 | ); 38 | 39 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 40 | public struct WKSTA_INFO_100 41 | { 42 | public int platform_id; 43 | public string computer_name; 44 | public string lan_group; 45 | public int ver_major; 46 | public int ver_minor; 47 | } 48 | 49 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 50 | public struct SHARE_INFO_0 51 | { 52 | public string shi0_netname; 53 | } 54 | 55 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 56 | public struct SHARE_INFO_1 57 | { 58 | public string shi1_netname; 59 | public uint shi1_type; 60 | public string shi1_remark; 61 | public SHARE_INFO_1(string sharename, uint sharetype, string remark) 62 | { 63 | this.shi1_netname = sharename; 64 | this.shi1_type = sharetype; 65 | this.shi1_remark = remark; 66 | } 67 | public override string ToString() 68 | { 69 | return shi1_netname; 70 | } 71 | } 72 | 73 | const uint MAX_PREFERRED_LENGTH = 0xFFFFFFFF; 74 | const int NERR_Success = 0; 75 | 76 | private enum NetError : uint 77 | { 78 | NERR_Success = 0, 79 | NERR_BASE = 2100, 80 | NERR_UnknownDevDir = (NERR_BASE + 16), 81 | NERR_DuplicateShare = (NERR_BASE + 18), 82 | NERR_BufTooSmall = (NERR_BASE + 23), 83 | } 84 | 85 | private enum SHARE_TYPE : uint 86 | { 87 | STYPE_DISKTREE = 0, 88 | STYPE_PRINTQ = 1, 89 | STYPE_DEVICE = 2, 90 | STYPE_IPC = 3, 91 | STYPE_SPECIAL = 0x80000000, 92 | } 93 | 94 | public static SHARE_INFO_1[] EnumNetShares(string Server) 95 | { 96 | List ShareInfos = new List(); 97 | int entriesread = 0; 98 | int totalentries = 0; 99 | int resume_handle = 0; 100 | int nStructSize = Marshal.SizeOf(typeof(SHARE_INFO_1)); 101 | IntPtr bufPtr = IntPtr.Zero; 102 | StringBuilder server = new StringBuilder(Server); 103 | int ret = NetShareEnum(server, 1, ref bufPtr, MAX_PREFERRED_LENGTH, ref entriesread, ref totalentries, ref resume_handle); 104 | if (ret == NERR_Success) 105 | { 106 | IntPtr currentPtr = bufPtr; 107 | for (int i = 0; i < entriesread; i++) 108 | { 109 | SHARE_INFO_1 shi1 = (SHARE_INFO_1)Marshal.PtrToStructure(currentPtr, typeof(SHARE_INFO_1)); 110 | ShareInfos.Add(shi1); 111 | currentPtr += nStructSize; 112 | } 113 | NetApiBufferFree(bufPtr); 114 | return ShareInfos.ToArray(); 115 | } 116 | else 117 | { 118 | ShareInfos.Add(new SHARE_INFO_1("ERROR=" + ret.ToString(), 10, string.Empty)); 119 | return ShareInfos.ToArray(); 120 | } 121 | } 122 | 123 | 124 | 125 | public static List GetDomainControllers() 126 | { 127 | List domainControllers = new List(); 128 | try 129 | { 130 | Domain domain = Domain.GetCurrentDomain(); 131 | foreach (DomainController dc in domain.DomainControllers) 132 | { 133 | domainControllers.Add(dc); 134 | } 135 | } 136 | catch { } 137 | return domainControllers; 138 | } 139 | 140 | public static void GetComputerAddresses(List computers) 141 | { 142 | foreach (string computer in computers) 143 | { 144 | try 145 | { 146 | IPAddress[] ips = System.Net.Dns.GetHostAddresses(computer); 147 | foreach (IPAddress ip in ips) 148 | { 149 | if (!ip.ToString().Contains(":")) 150 | { 151 | Console.WriteLine("{0}: {1}", computer, ip); 152 | } 153 | } 154 | } 155 | catch(Exception ex) 156 | { 157 | //Console.WriteLine("[X] ERROR: {0}", ex.Message); 158 | } 159 | } 160 | } 161 | 162 | public static List GetComputers() 163 | { 164 | List computerNames = new List(); 165 | List dcs = GetDomainControllers(); 166 | if (dcs.Count > 0) 167 | { 168 | try 169 | { 170 | Domain domain = Domain.GetCurrentDomain(); 171 | //domain. 172 | string currentUser = WindowsIdentity.GetCurrent().Name.Split('\\')[1]; 173 | 174 | 175 | using (DirectoryEntry entry = new DirectoryEntry(String.Format("LDAP://{0}", dcs[0]))) 176 | { 177 | using (DirectorySearcher mySearcher = new DirectorySearcher(entry)) 178 | { 179 | mySearcher.Filter = ("(objectClass=computer)"); 180 | 181 | // No size limit, reads all objects 182 | mySearcher.SizeLimit = 0; 183 | 184 | // 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) 185 | mySearcher.PageSize = 250; 186 | 187 | // Let searcher know which properties are going to be used, and only load those 188 | mySearcher.PropertiesToLoad.Add("name"); 189 | 190 | foreach (SearchResult resEnt in mySearcher.FindAll()) 191 | { 192 | // Note: Properties can contain multiple values. 193 | if (resEnt.Properties["name"].Count > 0) 194 | { 195 | string computerName = (string)resEnt.Properties["name"][0]; 196 | computerNames.Add(computerName); 197 | } 198 | } 199 | } 200 | } 201 | } 202 | catch { } 203 | } 204 | else 205 | { 206 | Console.WriteLine("ERROR: Could not get a list of Domain Controllers."); 207 | } 208 | return computerNames; 209 | } 210 | 211 | public static void GetComputerShares(string computer) 212 | { 213 | string[] errors = { "ERROR=53", "ERROR=5" }; 214 | SHARE_INFO_1[] computerShares = EnumNetShares(computer); 215 | if (computerShares.Length > 0) 216 | { 217 | List readableShares = new List(); 218 | List unauthorizedShares = new List(); 219 | foreach (SHARE_INFO_1 share in computerShares) 220 | { 221 | try 222 | { 223 | string path = String.Format("\\\\{0}\\{1}", computer, share.shi1_netname); 224 | var files = System.IO.Directory.GetFiles(path); 225 | readableShares.Add(share.shi1_netname); 226 | } 227 | catch 228 | { 229 | if (!errors.Contains(share.shi1_netname)) 230 | { 231 | unauthorizedShares.Add(share.shi1_netname); 232 | } 233 | } 234 | } 235 | if (readableShares.Count > 0) 236 | { 237 | string output = ""; 238 | foreach (string share in readableShares) 239 | { 240 | output += string.Format("\\\\{0}\\{1}\r\n", computer, share); 241 | } 242 | lock(thisLock) 243 | { 244 | File.AppendAllText(@"shares.txt", output); 245 | } 246 | } 247 | } 248 | } 249 | 250 | public static void GetAllShares(List computers) 251 | { 252 | List runningThreads = new List(); 253 | foreach(string computer in computers) 254 | { 255 | Thread t = new Thread(() => GetComputerShares(computer)); 256 | t.Start(); 257 | runningThreads.Add(t); 258 | } 259 | foreach(Thread t in runningThreads) 260 | { 261 | t.Join(); 262 | } 263 | } 264 | 265 | static void GetComputerVersions(List computers) 266 | { 267 | String output = ""; 268 | foreach(string computer in computers) 269 | { 270 | output += String.Format("Computer: {0}\r\n", computer); 271 | string serverName = String.Format("\\\\{0}", computer); 272 | IntPtr buffer; 273 | var ret = NetWkstaGetInfo(serverName, 100, out buffer); 274 | var strut_size = Marshal.SizeOf(typeof(WKSTA_INFO_100)); 275 | if (ret == NERR_Success) 276 | { 277 | var info = (WKSTA_INFO_100)Marshal.PtrToStructure(buffer, typeof(WKSTA_INFO_100)); 278 | if (!string.IsNullOrEmpty(info.computer_name)) 279 | { 280 | output += String.Format("\t{0}\r\n", info.computer_name); 281 | output += String.Format("\t{0}\r\n", info.platform_id); 282 | output += String.Format("\t{0}\r\n",info.ver_major); 283 | output += String.Format("\t{0}\r\n",info.ver_minor); 284 | output += String.Format("\t{0}\r\n",info.lan_group); 285 | } 286 | } 287 | } 288 | System.IO.File.WriteAllLines(@"systeminfo.txt", computers); 289 | } 290 | 291 | static void Main(string[] args) 292 | { 293 | var computers = GetComputers(); 294 | System.IO.File.WriteAllLines(@"systems.txt", computers); 295 | 296 | Console.WriteLine("[*] Parsed {0} computer objects.", computers.Count); 297 | ThreadPool.SetMaxThreads(100, 100); 298 | //GetComputerAddresses(computers); 299 | GetAllShares(computers); 300 | // GetComputerVersions(computers); 301 | } 302 | } 303 | } 304 | --------------------------------------------------------------------------------