Exemplo n.º 1
0
        public void PrepDomainUserRules()
        {
            try
            {
                if (MyOptions.DomainUsersWordlistRules.Count >= 1)
                {
                    foreach (string ruleName in MyOptions.DomainUsersWordlistRules)
                    {
                        ClassifierRule configClassifierRule =
                            MyOptions.ClassifierRules.First(thing => thing.RuleName == ruleName);

                        foreach (string user in MyOptions.DomainUsersToMatch)
                        {
                            string pattern = "( |'|\")" + Regex.Escape(user) + "( |'|\")";
                            Regex  regex   = new Regex(pattern,
                                                       RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
                            configClassifierRule.Regexes.Add(regex);
                        }
                    }
                }
            }
            catch (Exception)
            {
                Mq.Error("Something went wrong adding domain users to rules.");
            }
        }
Exemplo n.º 2
0
        public void PrepDomainUserRules()
        {
            try
            {
                if (MyOptions.DomainUsersWordlistRules.Count >= 1)
                {
                    foreach (string ruleName in MyOptions.DomainUsersWordlistRules)
                    {
                        ClassifierRule configClassifierRule =
                            MyOptions.ClassifierRules.First(thing => thing.RuleName == ruleName);

                        foreach (string user in MyOptions.DomainUsersToMatch)
                        {
                            if (user.Length < MyOptions.DomainUserMinLen)
                            {
                                Mq.Trace(String.Format("Skipping regex for \"{0}\".  Shorter than minimum chars: {1}", user, MyOptions.DomainUserMinLen));
                                continue;
                            }

                            // Use the null character to match begin and end of line
                            string pattern = "(| |'|\")" + Regex.Escape(user) + "(| |'|\")";
                            Regex  regex   = new Regex(pattern,
                                                       RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant);
                            configClassifierRule.Regexes.Add(regex);
                            Mq.Trace(String.Format("Adding regex {0} to rule {1}", regex, ruleName));
                        }
                    }
                }
            }
            catch (Exception)
            {
                Mq.Error("Something went wrong adding domain users to rules.");
            }
        }
Exemplo n.º 3
0
        public AdData()
        {
            Mq = BlockingMq.GetMq();

            // figure out domain context
            if (MyOptions.TargetDomain == null && MyOptions.TargetDc == null)
            {
                try
                {
                    DirectoryContext =
                        new DirectoryContext(DirectoryContextType.Domain, Domain.GetCurrentDomain().Name);
                }
                catch (Exception e)
                {
                    Mq.Error(
                        "Problem figuring out DirectoryContext, you might need to define manually with -d and/or -c.");
                    Mq.Degub(e.ToString());
                    Mq.Terminate();
                }
            }
            else if (!String.IsNullOrEmpty(MyOptions.TargetDc))
            {
                DirectoryContext = new DirectoryContext(DirectoryContextType.Domain, MyOptions.TargetDc);
            }
            else if (!String.IsNullOrEmpty(MyOptions.TargetDomain))
            {
                DirectoryContext = new DirectoryContext(DirectoryContextType.Domain, MyOptions.TargetDomain);
            }
            SetDomainUsersAndComputers();
        }
Exemplo n.º 4
0
        internal void GetComputerShares(string computer)
        {
            // find the shares
            HostShareInfo[] hostShareInfos = GetHostShareInfo(computer);

            foreach (HostShareInfo hostShareInfo in hostShareInfos)
            {
                string shareName = GetShareName(hostShareInfo, computer);
                if (!String.IsNullOrWhiteSpace(shareName))
                {
                    bool matched = false;

                    // classify them
                    foreach (ClassifierRule classifier in MyOptions.ShareClassifiers)
                    {
                        ShareClassifier shareClassifier = new ShareClassifier(classifier);
                        if (shareClassifier.ClassifyShare(shareName))
                        {
                            matched = true;
                            break;
                        }
                    }
                    // by default all shares should go on to TreeWalker unless the classifier pulls them out.
                    // send them to TreeWalker
                    if (!matched)
                    {
                        if (IsShareReadable(shareName))
                        {
                            ShareResult shareResult = new ShareResult()
                            {
                                Listable  = true,
                                SharePath = shareName
                            };
                            Mq.ShareResult(shareResult);

                            Mq.Info("Creating a TreeWalker task for " + shareResult.SharePath);
                            TreeTaskScheduler.New(() =>
                            {
                                try
                                {
                                    TreeWalker.WalkTree(shareResult.SharePath);
                                }
                                catch (Exception e)
                                {
                                    Mq.Error("Exception in TreeWalker task for share " + shareResult.SharePath);
                                    Mq.Error(e.ToString());
                                }
                            });
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        public override async Task EnqueueRequests(string ownerId, IEnumerable <Request> requests)
        {
            // 本机下载中心只会有一个下载代理
            var agents = await DownloaderAgentStore.GetAllListAsync(ownerId);

            if (agents.Count <= 0)
            {
                Logger.LogError("未找到活跃的下载器代理");
            }

            var agent = agents[0];
            var json  = JsonConvert.SerializeObject(requests);
            await Mq.PublishAsync(agent.Id, $"{Framework.DownloadCommand}|{json}");
        }
Exemplo n.º 6
0
 public void ScanFile(string file)
 {
     try
     {
         FileInfo fileInfo = new FileInfo(file);
         // send the file to all the classifiers.
         foreach (ClassifierRule classifier in MyOptions.FileClassifiers)
         {
             // Don't send file to classifier if interest level is not high enough
             if ((classifier.Triage == Triage.Red && InterestLevel > 2) ||
                 (classifier.Triage == Triage.Yellow && InterestLevel > 1) ||
                 (classifier.Triage == Triage.Green && InterestLevel > 0)
                 )
             {
                 continue;
             }
             FileClassifier fileClassifier = new FileClassifier(classifier);
             if (fileClassifier.ClassifyFile(fileInfo))
             {
                 return;
             }
             ;
         }
     }
     catch (FileNotFoundException e)
     {
         // If file was deleted by a separate application
         //  or thread since the call to TraverseTree()
         // then just continue.
         Mq.Trace(e.ToString());
         return;
     }
     catch (UnauthorizedAccessException e)
     {
         Mq.Trace(e.ToString());
         return;
     }
     catch (PathTooLongException)
     {
         Mq.Trace(file + " path was too long for me to look at.");
         return;
     }
     catch (Exception e)
     {
         Mq.Trace(e.ToString());
         return;
     }
 }
Exemplo n.º 7
0
        public TreeWalker(string shareRoot)
        {
            Mq = BlockingMq.GetMq();

            FileTaskScheduler = SnaffCon.GetFileTaskScheduler();

            if (shareRoot == null)
            {
                Mq.Trace("A null made it into TreeWalker. Wtf.");
                return;
            }

            Mq.Trace("About to start a TreeWalker on share " + shareRoot);
            WalkTree(shareRoot);
            Mq.Trace("Finished TreeWalking share " + shareRoot);
        }
Exemplo n.º 8
0
        private string GetShareName(HostShareInfo hostShareInfo, string computer)
        {
            // takes a HostShareInfo object and a computer name and turns it into a usable path.

            // first we want to throw away any errored out ones.
            string[] errors = { "ERROR=53", "ERROR=5" };
            if (errors.Contains(hostShareInfo.shi1_netname))
            {
                //Mq.Trace(hostShareInfo.shi1_netname + " on " + computer +
                //", but this is usually no cause for alarm.");
                return(null);
            }

            Mq.Degub("Share discovered: " + $"\\\\{computer}\\{hostShareInfo.shi1_netname}");

            return($"\\\\{computer}\\{hostShareInfo.shi1_netname}");
        }
Exemplo n.º 9
0
        public void Execute()
        {
            StartTime = DateTime.Now;
            // This is the main execution thread.
            Timer statusUpdateTimer =
                new Timer(TimeSpan.FromMinutes(1)
                          .TotalMilliseconds)
            {
                AutoReset = true
            };                        // Set the time (1 min in this case)

            statusUpdateTimer.Elapsed += TimedStatusUpdate;
            statusUpdateTimer.Start();

            // if we haven't been told what dir or computer to target, we're going to need to do share discovery. that means finding computers from the domain.
            if (MyOptions.PathTargets == null && MyOptions.ComputerTargets == null)
            {
                DomainDiscovery();
            }
            // if we've been told what computers to hit...
            else if (MyOptions.ComputerTargets != null)
            {
                ShareDiscovery(MyOptions.ComputerTargets);
            }
            // otherwise we should have a set of path targets...
            else if (MyOptions.PathTargets != null)
            {
                FileDiscovery(MyOptions.PathTargets);
            }
            // but if that hasn't been done, something has gone wrong.
            else
            {
                Mq.Error("OctoParrot says: AWK! I SHOULDN'T BE!");
            }

            waitHandle.WaitOne();

            StatusUpdate();
            DateTime finished = DateTime.Now;
            TimeSpan runSpan  = finished.Subtract(StartTime);

            Mq.Info("Finished at " + finished.ToLocalTime());
            Mq.Info("Snafflin' took " + runSpan);
            Mq.Finish();
        }
Exemplo n.º 10
0
 private void GetDomainControllers()
 {
     try
     {
         DomainControllerCollection dcCollection = DomainController.FindAll(DirectoryContext);
         foreach (DomainController dc in dcCollection)
         {
             DomainControllers.Add(dc.IPAddress);
         }
     }
     catch (Exception e)
     {
         Mq.Error(
             "Something went wrong trying to find domain controllers. Try defining manually with -c?");
         Mq.Degub(e.ToString());
         Mq.Terminate();
     }
 }
Exemplo n.º 11
0
        private void DomainUserDiscovery()
        {
            Mq.Info("Getting interesting users from AD.");
            // We do this single threaded cos it's fast and not easily divisible.

            // The AdData class set/get semantics have gotten wonky here.  Leaving as-is to minimize breakage/changes, but needs another look.
            AdData adData = new AdData();

            adData.SetDomainUsers();

            foreach (string user in adData.GetDomainUsers())
            {
                MyOptions.DomainUsersToMatch.Add(user);
            }

            // build the regexes for use in the file scans
            PrepDomainUserRules();
        }
Exemplo n.º 12
0
        private void DomainDfsDiscovery()
        {
            Dictionary <string, string> dfsSharesDict = null;
            AdData adData = null;

            Mq.Info("Getting DFS paths from AD.");

            adData = new AdData();

            adData.SetDfsPaths();
            dfsSharesDict = adData.GetDfsSharesDict();

            // if we found some actual dfsshares
            if (dfsSharesDict.Count >= 1)
            {
                MyOptions.DfsSharesDict     = dfsSharesDict;
                MyOptions.DfsNamespacePaths = adData.GetDfsNamespacePaths();
            }
        }
Exemplo n.º 13
0
        private void DomainDiscovery()
        {
            Mq.Info("Getting users and computers from AD.");
            // We do this single threaded cos it's fast and not easily divisible.
            AdData        adData          = new ActiveDirectory.AdData();
            List <string> targetComputers = adData.GetDomainComputers();

            if (targetComputers == null)
            {
                Mq.Error(
                    "Something f****d out finding stuff in the domain. You must be holding it wrong.");
                while (true)
                {
                    Mq.Terminate();
                }
            }
            string numTargetComputers = targetComputers.Count.ToString();

            Mq.Info("Got " + numTargetComputers + " computers from AD.");
            if (targetComputers.Count == 0)
            {
                Mq.Error("Didn't find any domain computers. Seems weird. Try pouring water on it.");
                while (true)
                {
                    Mq.Terminate();
                }
            }
            // Push list of fun users to Options
            if (MyOptions.DomainUserRules)
            {
                foreach (string user in adData.GetDomainUsers())
                {
                    MyOptions.DomainUsersToMatch.Add(user);
                }
                PrepDomainUserRules();
            }
            // immediately call ShareDisco which should handle the rest.
            ShareDiscovery(targetComputers.ToArray());
        }
Exemplo n.º 14
0
        private void FileDiscovery(string[] pathTargets)
        {
            foreach (string pathTarget in pathTargets)
            {
                // ShareScanner Task Creation - this kicks off the rest of the flow
                Mq.Info("Creating a TreeWalker task for " + pathTarget);
                TreeTaskScheduler.New(() =>
                {
                    try
                    {
                        TreeWalker.WalkTree(pathTarget);
                    }
                    catch (Exception e)
                    {
                        Mq.Error("Exception in TreeWalker task for path " + pathTarget);
                        Mq.Error(e.ToString());
                    }
                });
            }

            Mq.Info("Created all TreeWalker tasks.");
        }
Exemplo n.º 15
0
        public override async Task <bool> AllocateAsync(AllotDownloaderMessage allotDownloaderMessage)
        {
            List <DownloaderAgent> agents = null;

            for (int i = 0; i < 50; ++i)
            {
                agents = await DownloaderAgentStore.GetAllListAsync();

                if (agents.Count <= 0)
                {
                    Thread.Sleep(100);
                }
                else
                {
                    break;
                }
            }

            if (agents == null)
            {
                Logger.LogError("未找到活跃的下载器代理");
                return(false);
            }

            // 保存节点选取信息
            await DownloaderAgentStore.AllocateAsync(allotDownloaderMessage.OwnerId, new[] { agents[0].Id });

            Logger.LogInformation("下载器代理分配成功");
            // 发送消息让下载代理器分配好下载器
            var message =
                $"{Framework.AllocateDownloaderCommand}|{JsonConvert.SerializeObject(allotDownloaderMessage)}";

            foreach (var agent in agents)
            {
                await Mq.PublishAsync(agent.Id, message);
            }

            return(true);
        }
Exemplo n.º 16
0
 private void ShareDiscovery(string[] computerTargets)
 {
     Mq.Info("Starting to look for readable shares...");
     foreach (string computer in computerTargets)
     {
         // ShareFinder Task Creation - this kicks off the rest of the flow
         Mq.Trace("Creating a sharefinder task for " + computer);
         ShareTaskScheduler.New(() =>
         {
             try
             {
                 ShareFinder shareFinder = new ShareFinder();
                 shareFinder.GetComputerShares(computer);
             }
             catch (Exception e)
             {
                 Mq.Error("Exception in ShareFinder task for host " + computer);
                 Mq.Error(e.ToString());
             }
         });
     }
     Mq.Info("Created all sharefinder tasks.");
 }
Exemplo n.º 17
0
        private DirectorySearch GetDirectorySearcher()
        {
            Mq = BlockingMq.GetMq();

            // target domain and dc set
            if ((!string.IsNullOrEmpty(MyOptions.TargetDomain)) && (!string.IsNullOrEmpty(MyOptions.TargetDc)))
            {
                Mq.Trace("Target DC and Domain specified: " + MyOptions.TargetDomain + " + " + MyOptions.TargetDc);
                _targetDc     = MyOptions.TargetDc;
                _targetDomain = MyOptions.TargetDomain;
            }
            // no target DC or domain set
            else
            {
                Mq.Trace("Getting current domain from user context.");
                _currentDomain = Domain.GetCurrentDomain();
                _targetDomain  = _currentDomain.Name;
                _targetDc      = _targetDomain;
            }

            _targetDomainNetBIOSName = GetNetBiosDomainName();
            return(new DirectorySearch(_targetDomain, _targetDc));
        }
        /// <summary>
        /// 单机模式只有一个下载器代理
        /// </summary>
        /// <param name="allotDownloaderMessage">分配下载器代理的选项</param>
        /// <returns></returns>
        protected override async Task <bool> AllocateAsync(AllotDownloaderMessage allotDownloaderMessage)
        {
            var agent = Agents.Values.FirstOrDefault();

            if (agent == null)
            {
                Logger.LogInformation($"任务 {allotDownloaderMessage.OwnerId} 未找到可用的下载器代理");
                return(false);
            }

            // 保存节点选取信息
            await DownloaderAgentStore.AllocateAsync(allotDownloaderMessage.OwnerId, new[] { agent.Id });

            // 发送消息让下载代理器分配好下载器
            var message =
                $"|{Framework.AllocateDownloaderCommand}|{JsonConvert.SerializeObject(allotDownloaderMessage)}";

            await Mq.PublishAsync(agent.Id, message);

            Logger.LogInformation(
                $"任务 {allotDownloaderMessage.OwnerId} 分配下载代理器成功: {JsonConvert.SerializeObject(agent)}");
            return(true);
        }
Exemplo n.º 19
0
 private void ClassifyArchive(FileInfo fileInfo)
 {
     // look inside archives for files we like.
     try
     {
         IArchive archive = ArchiveFactory.Open(fileInfo.FullName);
         foreach (IArchiveEntry entry in archive.Entries)
         {
             if (!entry.IsDirectory)
             {
                 try
                 {
                     FileScanner.ScanFile(entry.Key);
                 }
                 catch (Exception e)
                 {
                     Mq.Trace(e.ToString());
                 }
             }
         }
     }
     catch (CryptographicException)
     {
         Mq.FileResult(new FileResult(fileInfo)
         {
             MatchedRule = new ClassifierRule()
             {
                 Triage = Triage.Black, RuleName = "EncryptedArchive"
             }
         });
     }
     catch (Exception e)
     {
         Mq.Trace(e.ToString());
     }
 }
Exemplo n.º 20
0
        private void ParseLogLevelString(string logLevelString)
        {
            switch (logLevelString.ToLower())
            {
            case "debug":
                LogLevel = LogLevel.Debug;
                Mq.Degub("Set verbosity level to degub.");
                break;

            case "degub":
                LogLevel = LogLevel.Debug;
                Mq.Degub("Set verbosity level to degub.");
                break;

            case "trace":
                LogLevel = LogLevel.Trace;
                Mq.Degub("Set verbosity level to trace.");
                break;

            case "data":
                LogLevel = LogLevel.Warn;
                Mq.Degub("Set verbosity level to data.");
                break;

            case "info":
                LogLevel = LogLevel.Info;
                Mq.Degub("Set verbosity level to info.");
                break;

            default:
                LogLevel = LogLevel.Info;
                Mq.Error("Invalid verbosity level " + logLevelString +
                         " falling back to default level (info).");
                break;
            }
        }
Exemplo n.º 21
0
        public void SetDomainComputers(string LdapFilter)
        {
            DirectorySearch ds = GetDirectorySearcher();

            List <string> domainComputers = new List <string>();

            try
            {
                if (!MyOptions.DfsOnly)
                {
                    // if we aren't limiting the scan to DFS shares then let's get some computer targets.

                    List <string> ldapPropertiesList = new List <string> {
                        "name", "dNSHostName", "lastLogonTimeStamp"
                    };
                    string ldapFilter = LdapFilter;

                    // extremely dirty hack to break a sig I once saw for Snaffler's LDAP queries. ;-)
                    int num = random.Next(1, 5);
                    while (num > 0)
                    {
                        Guid guid = Guid.NewGuid();
                        ldapPropertiesList.Add(guid.ToString());
                        --num;
                    }
                    string[] ldapProperties = ldapPropertiesList.ToArray();

                    IEnumerable <SearchResultEntry> searchResultEntries = ds.QueryLdap(ldapFilter, ldapProperties, System.DirectoryServices.Protocols.SearchScope.Subtree);

                    // set a window of "the last 4 months" - if a computer hasn't logged in to the domain in 4 months it's probably gone.
                    DateTime validLltsWindow = DateTime.Now.AddMonths(-4);
                    foreach (SearchResultEntry resEnt in searchResultEntries)
                    {
                        int  uacFlags;
                        bool success =
                            int.TryParse(resEnt.GetProperty("userAccountControl"),
                                         out uacFlags);

                        UserAccountControlFlags userAccFlags = (UserAccountControlFlags)uacFlags;

                        if (userAccFlags.HasFlag(UserAccountControlFlags.AccountDisabled))
                        {
                            continue;
                        }

                        try
                        {
                            // get the last logon timestamp value as a datetime
                            string lltsString = resEnt.GetProperty("lastlogontimestamp");
                            long   lltsLong;
                            long.TryParse(lltsString, out lltsLong);
                            DateTime lltsDateTime = DateTime.FromFileTime(lltsLong);
                            // compare it to our window, and if lltsDateTime is older, skip the computer acct.
                            if (lltsDateTime <= validLltsWindow)
                            {
                                continue;
                            }
                        }
                        catch (Exception e)
                        {
                            Mq.Error("Error calculating lastLogonTimeStamp for computer account " + resEnt.DistinguishedName);
                        }

                        if (!String.IsNullOrEmpty(resEnt.GetProperty("dNSHostName")))
                        {
                            string computerName = resEnt.GetProperty("dNSHostName");
                            domainComputers.Add(computerName);
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Mq.Trace(e.ToString());
            }

            this._domainComputers = domainComputers;
        }
Exemplo n.º 22
0
        private void SetDomainUsersAndComputers()
        {
            if (!String.IsNullOrEmpty(MyOptions.TargetDc))
            {
                DomainControllers.Add(MyOptions.TargetDc);
            }
            else
            {
                GetDomainControllers();
            }

            List <string> domainComputers = new List <string>();
            List <string> domainUsers     = new List <string>();

            // we do this so if the first one fails we keep trying til we find a DC we can talk to.

            foreach (string domainController in DomainControllers)
            {
                try
                {
                    // TODO add support for user defined creds here.

                    using (DirectoryEntry entry = new DirectoryEntry("LDAP://" + domainController))
                    {
                        using (DirectorySearcher mySearcher = new DirectorySearcher(entry))
                        {
                            mySearcher.Filter = ("(objectClass=computer)");

                            // No size limit, reads all objects
                            mySearcher.SizeLimit = 0;

                            // 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)
                            mySearcher.PageSize = 250;

                            // Let searcher know which properties are going to be used, and only load those
                            mySearcher.PropertiesToLoad.Add("name");
                            mySearcher.PropertiesToLoad.Add("dNSHostName");
                            mySearcher.PropertiesToLoad.Add("lastLogonTimeStamp");

                            foreach (SearchResult resEnt in mySearcher.FindAll())
                            {
                                // Note: Properties can contain multiple values.
                                if (resEnt.Properties["dNSHostName"].Count > 0)
                                {
                                    string computerName = (string)resEnt.Properties["dNSHostName"][0];
                                    domainComputers.Add(computerName);
                                }
                            }
                        }

                        this._domainComputers = domainComputers;

                        if (MyOptions.DomainUserRules)
                        {
                            // now users
                            using (DirectorySearcher mySearcher = new DirectorySearcher(entry))
                            {
                                mySearcher.Filter = ("(objectClass=user)");

                                // No size limit, reads all objects
                                mySearcher.SizeLimit = 0;

                                // 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)
                                mySearcher.PageSize = 250;

                                // Let searcher know which properties are going to be used, and only load those
                                mySearcher.PropertiesToLoad.Add("name");
                                mySearcher.PropertiesToLoad.Add("adminCount");
                                mySearcher.PropertiesToLoad.Add("sAMAccountName");
                                mySearcher.PropertiesToLoad.Add("userAccountControl");

                                foreach (SearchResult resEnt in mySearcher.FindAll())
                                {
                                    try
                                    {
                                        //busted account name
                                        if (resEnt.Properties["sAMAccountName"].Count == 0)
                                        {
                                            continue;
                                        }

                                        int  uacFlags;
                                        bool succes =
                                            int.TryParse(resEnt.Properties["userAccountControl"][0].ToString(),
                                                         out uacFlags);
                                        UserAccountControlFlags userAccFlags = (UserAccountControlFlags)uacFlags;

                                        if (userAccFlags.HasFlag(UserAccountControlFlags.AccountDisabled))
                                        {
                                            continue;
                                        }

                                        string userName = (string)resEnt.Properties["sAMAccountName"][0];

                                        // skip computer accounts
                                        if (userName.EndsWith("$"))
                                        {
                                            continue;
                                        }

                                        if (userName.IndexOf("mailbox", StringComparison.OrdinalIgnoreCase) >= 0)
                                        {
                                            continue;
                                        }

                                        if (userName.IndexOf("mbx", StringComparison.OrdinalIgnoreCase) >= 0)
                                        {
                                            continue;
                                        }

                                        // if it's got adminCount, keep it
                                        if (resEnt.Properties["adminCount"].Count != 0)
                                        {
                                            if (resEnt.Properties["adminCount"][0].ToString() == "1")
                                            {
                                                Mq.Trace("Adding " + userName +
                                                         " to target list because it had adminCount=1.");
                                                domainUsers.Add(userName);
                                                continue;
                                            }
                                        }

                                        // if the password doesn't expire it's probably a service account
                                        if (userAccFlags.HasFlag(UserAccountControlFlags.PasswordDoesNotExpire))
                                        {
                                            Mq.Trace("Adding " + userName +
                                                     " to target list because I think it's a service account.");
                                            domainUsers.Add(userName);
                                            continue;
                                        }

                                        if (userAccFlags.HasFlag(UserAccountControlFlags.DontRequirePreauth))
                                        {
                                            Mq.Trace("Adding " + userName +
                                                     " to target list because I think it's a service account.");
                                            domainUsers.Add(userName);
                                            continue;
                                        }

                                        if (userAccFlags.HasFlag(UserAccountControlFlags.TrustedForDelegation))
                                        {
                                            Mq.Trace("Adding " + userName +
                                                     " to target list because I think it's a service account.");
                                            domainUsers.Add(userName);
                                            continue;
                                        }

                                        if (userAccFlags.HasFlag(UserAccountControlFlags
                                                                 .TrustedToAuthenticateForDelegation))
                                        {
                                            Mq.Trace("Adding " + userName +
                                                     " to target list because I think it's a service account.");
                                            domainUsers.Add(userName);
                                            continue;
                                        }

                                        // if it matches a string we like, keep it
                                        foreach (string str in MyOptions.DomainUserMatchStrings)
                                        {
                                            if (userName.ToLower().Contains(str.ToLower()))
                                            {
                                                Mq.Trace("Adding " + userName +
                                                         " to target list because it contained " + str + ".");
                                                domainUsers.Add(userName);
                                                break;
                                            }
                                        }
                                    }
                                    catch (Exception e)
                                    {
                                        Mq.Trace(e.ToString());
                                        continue;
                                    }
                                }
                            }
                        }
                        this._domainUsers = domainUsers;
                    }

                    break;
                }
                catch (Exception e)
                {
                    Mq.Trace(e.ToString());
                    throw;
                }
            }
        }
Exemplo n.º 23
0
        private void StatusUpdate()
        {
            //lock (StatusObjectLocker)
            //{
            // get memory usage for status update
            string memorynumber;

            using (Process proc = Process.GetCurrentProcess())
            {
                long memorySize64 = proc.PrivateMemorySize64;
                memorynumber = BytesToString(memorySize64);
            }

            TaskCounters shareTaskCounters = ShareTaskScheduler.Scheduler.GetTaskCounters();
            TaskCounters treeTaskCounters  = TreeTaskScheduler.Scheduler.GetTaskCounters();
            TaskCounters fileTaskCounters  = FileTaskScheduler.Scheduler.GetTaskCounters();

            StringBuilder updateText = new StringBuilder("Status Update: \n");

            updateText.Append("ShareFinder Tasks Completed: " + shareTaskCounters.CompletedTasks + "\n");
            updateText.Append("ShareFinder Tasks Remaining: " + shareTaskCounters.CurrentTasksRemaining + "\n");
            updateText.Append("ShareFinder Tasks Running: " + shareTaskCounters.CurrentTasksRunning + "\n");
            updateText.Append("TreeWalker Tasks Completed: " + treeTaskCounters.CompletedTasks + "\n");
            updateText.Append("TreeWalker Tasks Remaining: " + treeTaskCounters.CurrentTasksRemaining + "\n");
            updateText.Append("TreeWalker Tasks Running: " + treeTaskCounters.CurrentTasksRunning + "\n");
            updateText.Append("FileScanner Tasks Completed: " + fileTaskCounters.CompletedTasks + "\n");
            updateText.Append("FileScanner Tasks Remaining: " + fileTaskCounters.CurrentTasksRemaining + "\n");
            updateText.Append("FileScanner Tasks Running: " + fileTaskCounters.CurrentTasksRunning + "\n");
            updateText.Append(memorynumber + " RAM in use." + "\n");
            updateText.Append("\n");

            // if all share tasks have finished, reduce max parallelism to 0 and reassign capacity to file scheduler.
            if (ShareTaskScheduler.Done() && (shareTaskCounters.MaxParallelism >= 1))
            {
                // get the current number of sharetask threads
                int transferVal = shareTaskCounters.MaxParallelism;
                // set it to zero
                ShareTaskScheduler.Scheduler._maxDegreeOfParallelism = 0;
                // add 1 to the other
                FileTaskScheduler.Scheduler._maxDegreeOfParallelism = FileTaskScheduler.Scheduler._maxDegreeOfParallelism + transferVal;
                updateText.Append("ShareScanner queue finished, rebalancing workload." + "\n");
            }

            // do other rebalancing

            if (fileTaskCounters.CurrentTasksQueued <= (MyOptions.MaxFileQueue / 20))
            {
                // but only if one side isn't already at minimum
                if (FileTaskScheduler.Scheduler._maxDegreeOfParallelism > 1)
                {
                    updateText.Append("Insufficient FileScanner queue size, rebalancing workload." + "\n");
                    --FileTaskScheduler.Scheduler._maxDegreeOfParallelism;
                    ++TreeTaskScheduler.Scheduler._maxDegreeOfParallelism;
                }
            }
            if (fileTaskCounters.CurrentTasksQueued == MyOptions.MaxFileQueue)
            {
                if (TreeTaskScheduler.Scheduler._maxDegreeOfParallelism > 1)
                {
                    updateText.Append("Max FileScanner queue size reached, rebalancing workload." + "\n");
                    ++FileTaskScheduler.Scheduler._maxDegreeOfParallelism;
                    --TreeTaskScheduler.Scheduler._maxDegreeOfParallelism;
                }
            }

            updateText.Append("Max ShareFinder Threads: " + ShareTaskScheduler.Scheduler._maxDegreeOfParallelism + "\n");
            updateText.Append("Max TreeWalker Threads: " + TreeTaskScheduler.Scheduler._maxDegreeOfParallelism + "\n");
            updateText.Append("Max FileScanner Threads: " + FileTaskScheduler.Scheduler._maxDegreeOfParallelism + "\n");

            DateTime now     = DateTime.Now;
            TimeSpan runSpan = now.Subtract(StartTime);

            updateText.Append("Been Snafflin' for " + runSpan + " and we ain't done yet..." + "\n");

            Mq.Info(updateText.ToString());

            if (FileTaskScheduler.Done() && ShareTaskScheduler.Done() && TreeTaskScheduler.Done())
            {
                waitHandle.Set();
            }
            //}
        }
Exemplo n.º 24
0
        public bool Parse(string[] args)
        {
            Mq.Info("Parsing args...");
            var success = false;

            // define args
            var outFileArg = new ValueArgument <string>('o', "outfile",
                                                        "Path for output file. You probably want this if you're not using -s.");
            var verboseArg = new ValueArgument <string>('v', "verbosity",
                                                        "Controls verbosity level, options are Trace (most verbose), Debug (less verbose), Info (less verbose still, default), and Data (results only). e.g '-v debug' ");
            var helpArg = new SwitchArgument('h', "help", "Displays this help.", false);
            //var extMatchArg = new ValueArgument<string>('e', "extmatch",
            //    "Path to wordlist for searching by exact extension match.");
            //var nameMatchArg = new ValueArgument<string>('n', "namematch",
            //    "Path to wordlist for searching by exact filename match.");
            //var grepMatchArg = new ValueArgument<string>('g', "grepmatch",
            //    "Path to wordlist for searching by grepping the contents of files with \"interesting\" extensions.");
            //var partialMatchArg = new ValueArgument<string>('p', "partialmatch",
            //    "Path to wordlist for searching by partial filename match.");
            //var pathMatchArg = new ValueArgument<string>('a', "pathmatch",
            //    "Path to wordlist for searching by partial path match.");
            //var extSkipMatchArg = new ValueArgument<string>('x', "extskipmatch",
            //    "Path to wordlist for extensions that should be skipped.");
            var stdOutArg = new SwitchArgument('s', "stdout",
                                               "Enables outputting results to stdout as soon as they're found. You probably want this if you're not using -o.",
                                               false);
            var mirrorArg = new ValueArgument <string>('m', "mirror",
                                                       "Enables and assigns an output dir for snaffler to automatically take a copy of any found files.");
            var fileHuntArg = new SwitchArgument('f', "filehuntoff",
                                                 "Disables file discovery, will only perform computer and share discovery.", false);
            var dirTargetArg = new ValueArgument <string>('i', "dirtarget",
                                                          "Disables computer and share discovery, requires a path to a directory in which to perform file discovery.");
            var maxThreadsArg = new ValueArgument <int>('t', "threads", "Maximum number of threads. Default 30.");
            var domainArg     = new ValueArgument <string>('d', "domain",
                                                           "Domain to search for computers to search for shares on to search for files in. Easy.");
            var adminshareArg = new SwitchArgument('a', "cdolla",
                                                   "Enables scanning of C$ shares if found. Can be prone to false positives but more thorough.", false);
            var domainControllerArg = new ValueArgument <string>('c', "domaincontroller",
                                                                 "Domain controller to query for a list of domain computers.");
            var maxGrepSizeArg = new ValueArgument <long>('r', "maxgrepsize",
                                                          "The maximum size file (in bytes) to search inside for interesting strings. Defaults to 500k.");
            var grepContextArg = new ValueArgument <int>('j', "grepcontext",
                                                         "How many bytes of context either side of found strings in files to show, e.g. -j 200");

            // list of letters i haven't used yet: bklquwyz

            var parser = new CommandLineParser.CommandLineParser();

            parser.Arguments.Add(outFileArg);
            parser.Arguments.Add(helpArg);
            //parser.Arguments.Add(extMatchArg);
            //parser.Arguments.Add(nameMatchArg);
            //parser.Arguments.Add(grepMatchArg);
            //parser.Arguments.Add(extSkipMatchArg);
            //parser.Arguments.Add(partialMatchArg);
            parser.Arguments.Add(stdOutArg);
            parser.Arguments.Add(mirrorArg);
            parser.Arguments.Add(fileHuntArg);
            parser.Arguments.Add(dirTargetArg);
            parser.Arguments.Add(maxThreadsArg);
            parser.Arguments.Add(domainArg);
            parser.Arguments.Add(verboseArg);
            parser.Arguments.Add(adminshareArg);
            parser.Arguments.Add(domainControllerArg);
            parser.Arguments.Add(maxGrepSizeArg);
            parser.Arguments.Add(grepContextArg);

            // extra check to handle builtin behaviour from cmd line arg parser
            if ((args.Contains("--help") || args.Contains("/?") || args.Contains("help") || args.Contains("-h") || args.Length == 0))
            {
                parser.ShowUsage();
                Environment.Exit(0);
            }

            try
            {
                parser.ParseCommandLine(args);

                // get the args into our config


                // output args
                if (outFileArg.Parsed && (outFileArg.Value != null))
                {
                    LogToFile   = true;
                    LogFilePath = outFileArg.Value;
                    Mq.Degub("Logging to file at " + LogFilePath);
                }

                // Set loglevel.
                if (verboseArg.Parsed)
                {
                    var logLevelString = verboseArg.Value;
                    switch (logLevelString.ToLower())
                    {
                    case "debug":
                        LogLevel = LogLevel.Debug;
                        Mq.Degub("Set verbosity level to degub.");
                        break;

                    case "degub":
                        LogLevel = LogLevel.Debug;
                        Mq.Degub("Set verbosity level to degub.");
                        break;

                    case "trace":
                        LogLevel = LogLevel.Trace;
                        Mq.Degub("Set verbosity level to trace.");
                        break;

                    case "data":
                        LogLevel = LogLevel.Warn;
                        Mq.Degub("Set verbosity level to data.");
                        break;

                    default:
                        LogLevel = LogLevel.Info;
                        Mq.Error("Invalid verbosity level " + logLevelString +
                                 " falling back to default level (info).");
                        break;
                    }
                }

                // if enabled, display findings to the console
                LogToConsole = stdOutArg.Parsed;
                Mq.Degub("Enabled logging to stdout.");

                if (maxThreadsArg.Parsed)
                {
                    MaxThreads = maxThreadsArg.Value;
                    Mq.Degub("Max threads set to " + maxThreadsArg.Value);
                }

                // args that tell us about targeting
                if ((domainArg.Parsed) && (domainArg.Value != null))
                {
                    TargetDomain = domainArg.Value;
                    Mq.Degub("Target domain is " + domainArg.Value);
                }

                if ((domainControllerArg.Parsed) && (domainControllerArg.Value != null))
                {
                    TargetDc = domainControllerArg.Value;
                    Mq.Degub("Target DC is " + domainControllerArg.Value);
                }

                if (dirTargetArg.Parsed)
                {
                    ShareFinderEnabled = false;
                    DirTarget          = dirTargetArg.Value;
                    Mq.Degub("Disabled finding shares.");
                    Mq.Degub("Target path is " + dirTargetArg.Value);
                }

                if (adminshareArg.Parsed)
                {
                    ScanCDollarShares = true;
                    Mq.Degub("Scanning of C$ shares enabled.");
                }

                // if the user passes the various MatchArgs with no value, that disables them.
                // Otherwise load their wordlist into the appropriate config item.

                /*
                 * if (extMatchArg.Parsed)
                 * {
                 *  if (extMatchArg.Value.Length <= 0)
                 *  {
                 *      ExactExtensionCheck = false;
                 *      Mq.Degub("Disabled matching based on exact file extension match.");
                 *  }
                 *  else
                 *  {
                 *      ExtensionsToKeep = File.ReadAllLines(extMatchArg.Value);
                 *      Mq.Degub("Using file at " + extMatchArg.Value + " for exact file extension matching.");
                 *  }
                 * }
                 *
                 * if (pathMatchArg.Parsed)
                 * {
                 *  if (pathMatchArg.Value.Length <= 0)
                 *  {
                 *      PartialPathCheck = false;
                 *      Mq.Degub("Disabled matching based on partial file path.");
                 *  }
                 *  else
                 *  {
                 *      PathsToKeep = File.ReadAllLines(pathMatchArg.Value);
                 *      Mq.Degub("Using file at " + pathMatchArg.Value + " for partial file path matching.");
                 *  }
                 * }
                 *
                 * if (extSkipMatchArg.Parsed)
                 * {
                 *  if (extSkipMatchArg.Value.Length <= 0)
                 *  {
                 *      ExactExtensionSkipCheck = false;
                 *      Mq.Degub("Disabled skipping files with extensions on skip-list.");
                 *  }
                 *  else
                 *  {
                 *      ExtSkipList = File.ReadAllLines(extSkipMatchArg.Value);
                 *      Mq.Degub("Using file at " + extSkipMatchArg.Value + " for extension skip-list.");
                 *  }
                 * }
                 *
                 * if (nameMatchArg.Parsed)
                 * {
                 *  if (nameMatchArg.Value.Length <= 0)
                 *  {
                 *      ExactNameCheck = false;
                 *      Mq.Degub("Disabled matching based on exact file name");
                 *  }
                 *  else
                 *  {
                 *      FileNamesToKeep = File.ReadAllLines(nameMatchArg.Value);
                 *      Mq.Degub("Using file at " + nameMatchArg.Value + " for exact file name matching.");
                 *  }
                 * }
                 *
                 * if (grepMatchArg.Parsed)
                 * {
                 *  if (grepMatchArg.Value.Length <= 0)
                 *  {
                 *      GrepByExtensionCheck = false;
                 *      Mq.Degub("Disabled matching based on file contents.");
                 *  }
                 *  else
                 *  {
                 *      GrepStrings = File.ReadAllLines(grepMatchArg.Value);
                 *      Mq.Degub("Using file at " + grepMatchArg.Value + " for file contents matching.");
                 *  }
                 * }
                 *
                 * if (partialMatchArg.Parsed)
                 * {
                 *  if (partialMatchArg.Value.Length <= 0)
                 *  {
                 *      PartialNameCheck = false;
                 *      Mq.Degub("Disabled partial file name matching.");
                 *  }
                 *  else
                 *  {
                 *      NameStringsToKeep = File.ReadAllLines(partialMatchArg.Value);
                 *      Mq.Degub("Using file at " + partialMatchArg.Value + " for partial file name matching.");
                 *  }
                 * }
                 */
                if (maxGrepSizeArg.Parsed)
                {
                    MaxSizeToGrep = maxGrepSizeArg.Value;
                    Mq.Degub("We won't bother looking inside files if they're bigger than " + MaxSizeToGrep + " bytes");
                }

                // how many bytes
                if (grepContextArg.Parsed)
                {
                    GrepContextBytes = grepContextArg.Value;
                    Mq.Degub(
                        "We'll show you " + grepContextArg.Value + " bytes of context around matches inside files.");
                }

                // if enabled, grab a copy of files that we like.
                if (mirrorArg.Parsed)
                {
                    if (mirrorArg.Value.Length <= 0)
                    {
                        Mq.Error("-m or -mirror arg requires a path value.");
                        throw new ArgumentException("Invalid argument combination.");
                    }

                    EnableMirror = true;
                    MirrorPath   = mirrorArg.Value.TrimEnd('\\');
                    Mq.Degub("Mirroring matched files to path " + MirrorPath);
                }

                if (!LogToConsole && !LogToFile)
                {
                    Mq.Error(
                        "\nYou didn't enable output to file or to the console so you won't see any results or debugs or anything. Your l0ss.");
                    throw new ArgumentException("Pointless argument combination.");
                }
            }
            catch (Exception e)
            {
                Mq.Error(e.ToString());
                throw;
            }
            success = true;
            return(success);
        }
Exemplo n.º 25
0
        public void WalkTree(string currentDir)
        {
            // Walks a tree checking files and generating results as it goes.

            if (!Directory.Exists(currentDir))
            {
                return;
            }

            try
            {
                string[] files = Directory.GetFiles(currentDir);
                // check if we actually like the files
                foreach (string file in files)
                {
                    FileTaskScheduler.New(() =>
                    {
                        try
                        {
                            FileScanner.ScanFile(file);
                        }
                        catch (Exception e)
                        {
                            Mq.Error("Exception in FileScanner task for file " + file);
                            Mq.Trace(e.ToString());
                        }
                    });
                }
            }
            catch (UnauthorizedAccessException)
            {
                //Mq.Trace(e.ToString());
                //continue;
            }
            catch (DirectoryNotFoundException)
            {
                //Mq.Trace(e.ToString());
                //continue;
            }
            catch (IOException)
            {
                //Mq.Trace(e.ToString());
                //continue;
            }
            catch (Exception e)
            {
                Mq.Degub(e.ToString());
                //continue;
            }

            try
            {
                string[] subDirs = Directory.GetDirectories(currentDir);
                // Create a new treewalker task for each subdir.
                if (subDirs.Length >= 1)
                {
                    foreach (string dirStr in subDirs)
                    {
                        bool scanDir = true;
                        foreach (ClassifierRule classifier in MyOptions.DirClassifiers)
                        {
                            try
                            {
                                DirClassifier dirClassifier = new DirClassifier(classifier);
                                DirResult     dirResult     = dirClassifier.ClassifyDir(dirStr);

                                if (dirResult.ScanDir == false)
                                {
                                    scanDir = false;
                                    break;
                                }
                            }
                            catch (Exception e)
                            {
                                Mq.Trace(e.ToString());
                                continue;
                            }
                        }
                        if (scanDir == true)
                        {
                            TreeTaskScheduler.New(() =>
                            {
                                try
                                {
                                    WalkTree(dirStr);
                                }
                                catch (Exception e)
                                {
                                    Mq.Error("Exception in TreeWalker task for dir " + dirStr);
                                    Mq.Error(e.ToString());
                                }
                            });
                        }
                        else
                        {
                            Mq.Trace("Skipped scanning on " + dirStr + " due to Discard rule match.");
                        }
                    }
                }
            }
            catch (UnauthorizedAccessException)
            {
                //Mq.Trace(e.ToString());
                //continue;
            }
            catch (DirectoryNotFoundException)
            {
                //Mq.Trace(e.ToString());
                //continue;
            }
            catch (IOException)
            {
                //Mq.Trace(e.ToString());
                //continue;
            }
            catch (Exception e)
            {
                Mq.Trace(e.ToString());
                //continue;
            }
        }
Exemplo n.º 26
0
        public void WalkTree(string shareRoot)
        {
            try
            {
                // Walks a tree checking files and generating results as it goes.
                Stack <string> dirs = new Stack <string>(20);

                if (!Directory.Exists(shareRoot))
                {
                    return;
                }

                dirs.Push(shareRoot);

                while (dirs.Count > 0)
                {
                    string   currentDir = dirs.Pop();
                    string[] subDirs;
                    try
                    {
                        subDirs = Directory.GetDirectories(currentDir);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        //Mq.Trace(e.ToString());
                        continue;
                    }
                    catch (DirectoryNotFoundException)
                    {
                        //Mq.Trace(e.ToString());
                        continue;
                    }
                    catch (Exception e)
                    {
                        Mq.Trace(e.ToString());
                        continue;
                    }

                    string[] files = null;
                    try
                    {
                        files = Directory.GetFiles(currentDir);
                    }
                    catch (UnauthorizedAccessException)
                    {
                        //Mq.Trace(e.ToString());
                        continue;
                    }
                    catch (DirectoryNotFoundException)
                    {
                        //Mq.Trace(e.ToString());
                        continue;
                    }
                    catch (Exception e)
                    {
                        Mq.Trace(e.ToString());
                        continue;
                    }

                    // check if we actually like the files
                    foreach (string file in files)
                    {
                        FileTaskScheduler.New(() =>
                        {
                            try
                            {
                                FileScanner fileScanner = new FileScanner(file);
                            }
                            catch (Exception e)
                            {
                                Mq.Trace(e.ToString());
                            }
                        });
                    }

                    // Push the subdirectories onto the stack for traversal if they aren't on any discard-lists etc.
                    foreach (string dirStr in subDirs)
                    {
                        foreach (ClassifierRule classifier in MyOptions.DirClassifiers)
                        {
                            try
                            {
                                DirClassifier dirClassifier = new DirClassifier(classifier);
                                DirResult     dirResult     = dirClassifier.ClassifyDir(dirStr);
                                // TODO: concurrency uplift: when there is a pooled concurrency queue, just add the dir as a job to the queue
                                if (dirResult.ScanDir)
                                {
                                    dirs.Push(dirStr);
                                }
                            }
                            catch (Exception e)
                            {
                                Mq.Trace(e.ToString());
                                continue;
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Mq.Error(e.ToString());
            }
        }
Exemplo n.º 27
0
        public void SetDomainUsers()
        {
            DirectorySearch ds          = GetDirectorySearcher();
            List <string>   domainUsers = new List <string>();

            string[] ldapProperties = new string[] { "name", "adminCount", "sAMAccountName", "userAccountControl", "servicePrincipalName", "userPrincipalName" };
            string   ldapFilter     = "(&(objectClass=user)(objectCategory=person))";

            IEnumerable <SearchResultEntry> searchResultEntries = ds.QueryLdap(ldapFilter, ldapProperties, System.DirectoryServices.Protocols.SearchScope.Subtree);

            foreach (SearchResultEntry resEnt in searchResultEntries)
            {
                bool keepUser = false;
                try
                {
                    //busted account name
                    if (String.IsNullOrEmpty(resEnt.GetProperty("sAMAccountName")))
                    {
                        continue;
                    }

                    int  uacFlags;
                    bool success =
                        int.TryParse(resEnt.GetProperty("userAccountControl"),
                                     out uacFlags);
                    UserAccountControlFlags userAccFlags = (UserAccountControlFlags)uacFlags;

                    if (userAccFlags.HasFlag(UserAccountControlFlags.AccountDisabled))
                    {
                        continue;
                    }

                    string userName = resEnt.GetProperty("sAMAccountName");

                    if (userName.EndsWith("$"))
                    {
                        Mq.Trace("Skipping " + userName +
                                 " because it appears to be a computer or trust account.");
                        continue;
                    }

                    //skip mailboxy accounts - domains always have a billion of these.
                    if (userName.IndexOf("mailbox", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Mq.Trace("Skipping " + userName +
                                 " because it appears to be a mailbox.");
                        continue;
                    }

                    if (userName.IndexOf("mbx", StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        Mq.Trace("Skipping " + userName +
                                 " because it appears to be a mailbox.");
                        continue;
                    }

                    // if has an SPN, keep it
                    if (!keepUser && resEnt.GetProperty("servicePrincipalName") != null)
                    {
                        Mq.Trace("Adding " + userName +
                                 " to target list because it has an SPN");
                        keepUser = true;
                    }

                    // if it's got adminCount, keep it
                    if (!keepUser && resEnt.GetProperty("adminCount") == "1")
                    {
                        Mq.Trace("Adding " + userName +
                                 " to target list because it had adminCount=1.");
                        keepUser = true;
                    }

                    // if the password doesn't expire it's probably a service account
                    if (!keepUser && userAccFlags.HasFlag(UserAccountControlFlags.PasswordDoesNotExpire))
                    {
                        Mq.Trace("Adding " + userName +
                                 " to target list because password does not expire,  probably service account.");
                        keepUser = true;
                    }

                    if (!keepUser && userAccFlags.HasFlag(UserAccountControlFlags.DontRequirePreauth))
                    {
                        Mq.Trace("Adding " + userName +
                                 " to target list because it doesn't require Kerberos pre-auth.");
                        keepUser = true;
                    }

                    if (!keepUser && userAccFlags.HasFlag(UserAccountControlFlags.TrustedForDelegation))
                    {
                        Mq.Trace("Adding " + userName +
                                 " to target list because it is trusted for delegation.");
                        keepUser = true;
                    }

                    if (!keepUser && userAccFlags.HasFlag(UserAccountControlFlags
                                                          .TrustedToAuthenticateForDelegation))
                    {
                        Mq.Trace("Adding " + userName +
                                 " to target list because it is trusted for delegation.");
                        keepUser = true;
                    }

                    // Included patterns
                    if (!keepUser)
                    {
                        foreach (string str in MyOptions.DomainUserMatchStrings)
                        {
                            if (userName.ToLower().Contains(str.ToLower()))
                            {
                                Mq.Trace("Adding " + userName +
                                         " to target list because it contained " + str + ".");
                                keepUser = true;
                                break;
                            }
                        }
                    }


                    // Finished testing
                    if (!keepUser)
                    {
                        continue;
                    }

                    // Must have matched something
                    // For common/frequent names,  force fully-qualified strict formats
                    if (MyOptions.DomainUserStrictStrings.Contains(userName, StringComparer.OrdinalIgnoreCase))
                    {
                        Mq.Trace("Using strict formats for " + userName + ".");

                        domainUsers.Add(String.Format(@"{0}\{1}", _targetDomainNetBIOSName, userName));

                        if (!string.IsNullOrEmpty(resEnt.GetProperty("userPrincipalName")))
                        {
                            domainUsers.Add(resEnt.GetProperty("userPrincipalName"));
                        }

                        continue;
                    }

                    // Otherwise, go with the format preference from the config file
                    foreach (DomainUserNamesFormat dnuf in MyOptions.DomainUserNameFormats)
                    {
                        switch (dnuf)
                        {
                        case DomainUserNamesFormat.NetBIOS:
                            domainUsers.Add(String.Format(@"{0}\{1}", _targetDomainNetBIOSName, userName));
                            break;

                        case DomainUserNamesFormat.UPN:
                            if (!string.IsNullOrEmpty(resEnt.GetProperty("userPrincipalName")))
                            {
                                domainUsers.Add(resEnt.GetProperty("userPrincipalName"));
                            }
                            else
                            {
                                Mq.Trace("Adding " + userName + " with simple sAMAccountName because UPN is missing.");
                                domainUsers.Add(userName);
                            }
                            break;

                        case DomainUserNamesFormat.sAMAccountName:
                            domainUsers.Add(userName);
                            break;
                        }
                    }
                }
                catch (Exception e)
                {
                    Mq.Trace(e.ToString());
                    continue;
                }
            }

            this._domainUsers = domainUsers;
        }
Exemplo n.º 28
0
        internal void GetComputerShares(string computer)
        {
            // find the shares
            HostShareInfo[] hostShareInfos = GetHostShareInfo(computer);

            foreach (HostShareInfo hostShareInfo in hostShareInfos)
            {
                string shareName = GetShareName(hostShareInfo, computer);
                if (!String.IsNullOrWhiteSpace(shareName))
                {
                    bool matched = false;

                    // SYSVOL and NETLOGON shares are replicated so they have special logic - do not use Classifiers for these
                    switch (hostShareInfo.shi1_netname.ToUpper())
                    {
                    case "SYSVOL":
                        if (MyOptions.ScanSysvol == true)
                        {
                            //  leave matched as false so that we don't suppress the TreeWalk for the first SYSVOL replica we see
                            //  toggle the flag so that any other shares replica will be skipped
                            MyOptions.ScanSysvol = false;
                            break;
                        }
                        matched = true;
                        break;

                    case "NETLOGON":
                        if (MyOptions.ScanNetlogon == true)
                        {
                            //  same as SYSVOL above
                            MyOptions.ScanNetlogon = false;
                            break;
                        }
                        matched = true;
                        break;

                    default:
                        // classify them
                        foreach (ClassifierRule classifier in MyOptions.ShareClassifiers)
                        {
                            ShareClassifier shareClassifier = new ShareClassifier(classifier);
                            if (shareClassifier.ClassifyShare(shareName))
                            {
                                matched = true;
                                break;
                            }
                        }
                        break;
                    }

                    // by default all shares should go on to TreeWalker unless the classifier pulls them out.
                    // send them to TreeWalker
                    if (!matched)
                    {
                        if (IsShareReadable(shareName))
                        {
                            ShareResult shareResult = new ShareResult()
                            {
                                Listable  = true,
                                SharePath = shareName
                            };
                            Mq.ShareResult(shareResult);

                            Mq.Info("Creating a TreeWalker task for " + shareResult.SharePath);
                            TreeTaskScheduler.New(() =>
                            {
                                try
                                {
                                    TreeWalker.WalkTree(shareResult.SharePath);
                                }
                                catch (Exception e)
                                {
                                    Mq.Error("Exception in TreeWalker task for share " + shareResult.SharePath);
                                    Mq.Error(e.ToString());
                                }
                            });
                        }
                    }
                }
            }
        }
Exemplo n.º 29
0
        internal void GetComputerShares(string computer)
        {
            // find the shares
            HostShareInfo[] hostShareInfos = GetHostShareInfo(computer);

            foreach (HostShareInfo hostShareInfo in hostShareInfos)
            {
                // skip IPC$ and PRINT$ shares for #OPSEC!!!
                List <string> neverScan = new List <string> {
                    "ipc$", "print$"
                };
                if (neverScan.Contains(hostShareInfo.shi1_netname.ToLower()))
                {
                    continue;
                }

                string shareName = GetShareName(hostShareInfo, computer);
                if (!String.IsNullOrWhiteSpace(shareName))
                {
                    bool matched = false;

                    // SYSVOL and NETLOGON shares are replicated so they have special logic - do not use Classifiers for these
                    switch (hostShareInfo.shi1_netname.ToUpper())
                    {
                    case "SYSVOL":
                        if (MyOptions.ScanSysvol == true)
                        {
                            //  Leave matched as false so that we don't suppress the TreeWalk for the first SYSVOL replica we see.
                            //  Toggle the flag so that any other shares replica will be skipped
                            MyOptions.ScanSysvol = false;
                            break;
                        }
                        matched = true;
                        break;

                    case "NETLOGON":
                        if (MyOptions.ScanNetlogon == true)
                        {
                            //  Same logic as SYSVOL above
                            MyOptions.ScanNetlogon = false;
                            break;
                        }
                        matched = true;
                        break;

                    default:
                        // classify them
                        foreach (ClassifierRule classifier in MyOptions.ShareClassifiers)
                        {
                            ShareClassifier shareClassifier = new ShareClassifier(classifier);
                            if (shareClassifier.ClassifyShare(shareName))
                            {
                                // in this instance 'matched' means 'matched a discard rule, so don't send to treewalker'.
                                matched = true;
                                break;
                            }
                        }
                        break;
                    }

                    // by default all shares should go on to TreeWalker unless the classifier pulls them out.
                    // send them to TreeWalker
                    if (!matched)
                    {
                        // At least one classifier was matched so we will return this share to the results
                        ShareResult shareResult = new ShareResult()
                        {
                            Listable     = true,
                            SharePath    = shareName,
                            ShareComment = hostShareInfo.shi1_remark.ToString()
                        };

                        // Try to find this computer+share in the list of DFS targets


                        /*
                         *                      foreach (DFSShare dfsShare in MyOptions.DfsShares)
                         *                      {
                         *                          ///TODO: Add some logic to match cases where short hostnames is used in DFS target list
                         *                          if (dfsShare.RemoteServerName.Equals(computer, StringComparison.OrdinalIgnoreCase) &&
                         *                              dfsShare.Name.Equals(hostShareInfo.shi1_netname, StringComparison.OrdinalIgnoreCase))
                         *                          {
                         *                              // why the not operator?   if (!MyOptions.DfsNamespacePaths.Contains(dfsShare.DfsNamespacePath))
                         *                              if (MyOptions.DfsNamespacePaths.Contains(dfsShare.DfsNamespacePath))
                         *                              {
                         *                                  // remove the namespace path to make sure we don't kick it off again.
                         *                                  MyOptions.DfsNamespacePaths.Remove(dfsShare.DfsNamespacePath);
                         *                                  // sub out the \\computer\share path for the dfs namespace path. this makes sure we hit the most efficient endpoint.
                         *                                  shareName = dfsShare.DfsNamespacePath;
                         *                              }
                         *                              else // if that dfs namespace has already been removed from our list, skip further scanning of that share.
                         *                              {
                         *                                  skip = true;
                         *                              }
                         *
                         *                              // Found DFS target matching this computer+share - no further comparisons needed
                         *                              break;
                         *                          }
                         *                      }
                         */


                        // If this path can be accessed via DFS
                        if (MyOptions.DfsSharesDict.ContainsKey(shareName))
                        {
                            string dfsUncPath = MyOptions.DfsSharesDict[shareName];

                            Mq.Degub(String.Format("Matched host path {0} to DFS {1}", shareName, dfsUncPath));

                            // and if we haven't already scanned this share
                            if (MyOptions.DfsNamespacePaths.Contains(dfsUncPath))
                            {
                                Mq.Degub(String.Format("Will scan {0} using DFS referral instead of explicit host", dfsUncPath));

                                // sub out the \\computer\share path for the dfs namespace path. this makes sure we hit the most efficient endpoint.
                                shareResult.SharePath = dfsUncPath;

                                // remove the namespace path to make sure we don't kick it off again.
                                MyOptions.DfsNamespacePaths.Remove(dfsUncPath);
                            }
                            else // if that dfs path has already been removed from our list, skip further scanning of that share.
                            {
                                // Do we want to report a gray share result for these?  I think not.
                                // Mq.ShareResult(shareResult);
                                break;
                            }
                        }

                        //  If the share is readable then dig deeper.
                        if (IsShareReadable(shareResult.SharePath))
                        {
                            // Share is readable, report as green  (the old default/min of the Triage enum )
                            shareResult.Triage = Triage.Green;

                            try
                            {
                                DirectoryInfo dirInfo = new DirectoryInfo(shareResult.SharePath);

                                //EffectivePermissions.RwStatus rwStatus = effectivePermissions.CanRw(dirInfo);

                                shareResult.RootModifyable = false;
                                shareResult.RootWritable   = false;
                                shareResult.RootReadable   = true;

                                /*
                                 * if (rwStatus.CanWrite || rwStatus.CanModify)
                                 * {
                                 *  triage = Triage.Yellow;
                                 * }
                                 */
                            }
                            catch (System.UnauthorizedAccessException e)
                            {
                                Mq.Error("Failed to get permissions on " + shareResult.SharePath);
                            }

                            if (MyOptions.ScanFoundShares)
                            {
                                Mq.Trace("Creating a TreeWalker task for " + shareResult.SharePath);
                                TreeTaskScheduler.New(() =>
                                {
                                    try
                                    {
                                        TreeWalker.WalkTree(shareResult.SharePath);
                                    }
                                    catch (Exception e)
                                    {
                                        Mq.Error("Exception in TreeWalker task for share " + shareResult.SharePath);
                                        Mq.Error(e.ToString());
                                    }
                                });
                            }
                            Mq.ShareResult(shareResult);
                        }
                        else if (MyOptions.LogDeniedShares == true)
                        {
                            Mq.ShareResult(shareResult);
                        }
                    }
                }
            }
        }
Exemplo n.º 30
0
        public void SetDfsPaths()
        {
            DirectorySearch ds = GetDirectorySearcher();

            try
            {
                Mq.Degub("Starting DFS Enumeration.");

                DfsFinder       dfsFinder = new DfsFinder();
                List <DFSShare> dfsShares = dfsFinder.FindDfsShares(ds);

                _dfsSharesDict     = new Dictionary <string, string>(StringComparer.InvariantCultureIgnoreCase);
                _dfsNamespacePaths = new List <string>();
                string realPath;

                foreach (DFSShare dfsShare in dfsShares)
                {
                    // Construct the UNC path to this DFS share and add it to the list.
                    // We use this structure as a to-do list in the ShareFinder code, skipping DFS shares that have already been processed
                    string        dfsShareNamespacePath = @"\\" + _targetDomain + @"\" + dfsShare.DFSNamespace;
                    List <string> hostnames             = new List <string>();

                    if (!_dfsNamespacePaths.Contains(dfsShareNamespacePath))
                    {
                        _dfsNamespacePaths.Add(dfsShareNamespacePath);
                    }

                    // Calculate a long and a short name version for each "real" share path in lowercase.  Admins can set either in AD and
                    //    we may get either for our scan (depending on how we got our computer list.
                    // This simplifies the cross-referencing of actual server shares back to DFS paths in the ShareFinder code.

                    hostnames.Add(dfsShare.RemoteServerName);

                    if (dfsShare.RemoteServerName.EndsWith(_targetDomain, StringComparison.OrdinalIgnoreCase))
                    {   // share path has FQDN so crack out the short hostname
                        hostnames.Add(dfsShare.RemoteServerName.Split('.')[0]);
                    }
                    else
                    {   // share path has short name so append domain for FQDN
                        hostnames.Add(String.Format("{0}.{1}", dfsShare.RemoteServerName, _targetDomain));
                    }

                    // Add these paths as keys in the dictionary
                    foreach (string h in hostnames)
                    {
                        realPath = String.Format(@"\\{0}\{1}", h, dfsShare.Name);

                        if (!_dfsSharesDict.ContainsKey(realPath))
                        {
                            _dfsSharesDict.Add(realPath, dfsShareNamespacePath);
                        }
                    }
                }

                Mq.Info("Found " + _dfsSharesDict.Count.ToString() + " DFS Shares in " + _dfsNamespacePaths.Count.ToString() + " namespaces.");

                Mq.Degub("Finished DFS Enumeration.");
            }
            catch (Exception e)
            {
                Mq.Trace(e.ToString());
            }
        }