diff --git a/SharpShares/Program.cs b/SharpShares/Program.cs index 3f8883d..98c5076 100644 --- a/SharpShares/Program.cs +++ b/SharpShares/Program.cs @@ -18,6 +18,10 @@ static void Main(string[] args) bool success = Utilities.Options.PrintOptions(arguments); if (success) { + if (!String.IsNullOrEmpty(arguments.targets)) + { + hosts = new SharpShares.Utilities.IPRange(arguments.targets).GetAllIP().Select(ip => ip.ToString()).ToList(); + } if (!String.IsNullOrEmpty(arguments.ldap)) { List ldap = Utilities.LDAP.SearchLDAP(arguments); diff --git a/SharpShares/SharpShares.csproj b/SharpShares/SharpShares.csproj index bc83184..322a620 100644 --- a/SharpShares/SharpShares.csproj +++ b/SharpShares/SharpShares.csproj @@ -47,6 +47,7 @@ + diff --git a/SharpShares/Utilities/IPRange.cs b/SharpShares/Utilities/IPRange.cs new file mode 100644 index 0000000..0960f4f --- /dev/null +++ b/SharpShares/Utilities/IPRange.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Net; +using System.Text.RegularExpressions; + +namespace SharpShares.Utilities +{ + // from https://stackoverflow.com/questions/4172677/c-enumerate-ip-addresses-in-a-range + internal class IPRange + { + public IPRange(string ipRange) + { + if (ipRange == null) + throw new ArgumentNullException(); + + if (!TryParseCIDRNotation(ipRange) && !TryParseSimpleRange(ipRange)) + throw new ArgumentException(); + } + + public IEnumerable GetAllIP() + { + int capacity = 1; + for (int i = 0; i < 4; i++) + capacity *= endIP[i] - beginIP[i] + 1; + + List ips = new List(capacity); + for (int i0 = beginIP[0]; i0 <= endIP[0]; i0++) + { + for (int i1 = beginIP[1]; i1 <= endIP[1]; i1++) + { + for (int i2 = beginIP[2]; i2 <= endIP[2]; i2++) + { + for (int i3 = beginIP[3]; i3 <= endIP[3]; i3++) + { + ips.Add(new IPAddress(new byte[] { (byte)i0, (byte)i1, (byte)i2, (byte)i3 })); + } + } + } + } + + return ips; + } + + /// + /// Parse IP-range string in CIDR notation. + /// For example "12.15.0.0/16". + /// + /// + /// + private bool TryParseCIDRNotation(string ipRange) + { + string[] x = ipRange.Split('/'); + + if (x.Length != 2) + return false; + + byte bits = byte.Parse(x[1]); + uint ip = 0; + String[] ipParts0 = x[0].Split('.'); + + // if the user entered an incorrect CIRD range e.g. 172.18.100.50/24 which should be 172.18.100.0/24, fix it + if (uint.Parse(ipParts0[3]) > 0 && bits != 32) + { + ipParts0[3] = "0"; + } + + for (int i = 0; i < 4; i++) + { + ip = ip << 8; + ip += uint.Parse(ipParts0[i]); + } + + byte shiftBits = (byte)(32 - bits); + uint ip1 = (ip >> shiftBits) << shiftBits; + + if (ip1 != ip) // Check correct subnet address + return false; + + uint ip2 = ip1 >> shiftBits; + for (int k = 0; k < shiftBits; k++) + { + ip2 = (ip2 << 1) + 1; + } + + beginIP = new byte[4]; + endIP = new byte[4]; + + for (int i = 0; i < 4; i++) + { + beginIP[i] = (byte)((ip1 >> (3 - i) * 8) & 255); + endIP[i] = (byte)((ip2 >> (3 - i) * 8) & 255); + } + + return true; + } + + + /// + /// Parse IP-range string "12.15-16.1-30.10-255" + /// + /// + /// + private bool TryParseSimpleRange(string ipRange) + { + String[] ipParts = ipRange.Split('.'); + + beginIP = new byte[4]; + endIP = new byte[4]; + for (int i = 0; i < 4; i++) + { + string[] rangeParts = ipParts[i].Split('-'); + + if (rangeParts.Length < 1 || rangeParts.Length > 2) + return false; + + beginIP[i] = byte.Parse(rangeParts[0]); + endIP[i] = (rangeParts.Length == 1) ? beginIP[i] : byte.Parse(rangeParts[1]); + } + + return true; + } + + private byte[] beginIP; + private byte[] endIP; + } +} diff --git a/SharpShares/Utilities/Options.cs b/SharpShares/Utilities/Options.cs index bbed146..ac992eb 100644 --- a/SharpShares/Utilities/Options.cs +++ b/SharpShares/Utilities/Options.cs @@ -102,7 +102,7 @@ public static Arguments ArgumentValues(Dictionary parsedArgs) arguments = null; } // if no ldap or ou filter specified, search all enabled computer objects - if (!(parsedArgs.ContainsKey("/ldap")) && !(parsedArgs.ContainsKey("/ou"))) + if (!(parsedArgs.ContainsKey("/ldap")) && !(parsedArgs.ContainsKey("/ou")) && !(parsedArgs.ContainsKey("/targets"))) { Console.WriteLine("[!] Must specify hosts using one of the following arguments: /ldap /ou"); Utilities.Options.Usage(); @@ -183,6 +183,7 @@ public static void Usage() :servers-exclude-dc - All enabled servers excluding Domain Controllers or read-only DCs /ou - specify LDAP OU to query enabled computer objects from ex: ""OU=Special Servers,DC=example,DC=local"" + /targets - target range provided in CIDR notation (e.g. 192.168.100.0/24) or in the format 192.168.0-255.0-255. /stealth - list share names without performing read/write access checks /filter - list of comma-separated shares to exclude from enumeration default: SYSVOL,NETLOGON,IPC$,PRINT$