Example #1
0
        /// <summary>
        /// Contacts the server from our beacon loop
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        public bool ContactServer(NHibernate.ISession session)
        {
            bool ContactedServer = false;

            // Get info about all the new process events
            var processEvents = session.QueryOver <ProcessEvent>()
                                .Where(e => e.HasInformedServer == false)
                                .List <ProcessEvent>();

            if (processEvents.Count() != 0)
            {
                foreach (var processEvent in processEvents)
                {
                    // Get info about the exe associated ith this process

                    Executable executable = null;
                    try
                    {
                        executable = session.QueryOver <Executable>()
                                     .Where(e => e.Id == processEvent.ExecutableId)
                                     .List <Executable>().First();
                    }
                    catch (Exception e)
                    {
                        // TODO Need to log this error
                        Log.Exception(e, "Unable to find an executable for process event {0}", processEvent.Id);
                        // I'll record in the DB that we already informed the server about this broken event
                    }

                    using (var transaction = session.BeginTransaction())
                    {
                        if (executable == null)
                        {
                            // The executable for this process event was not found, so something broke, so just ignore it
                            processEvent.HasInformedServer = true;
                            session.Save(processEvent);
                            transaction.Commit();
                        }
                        else
                        {
                            if (Event.PostProcessEvent(processEvent, executable))
                            {
                                // Record that we sent this data to the server so we don't try sending it again
                                processEvent.HasInformedServer = true;
                                session.Save(processEvent);
                                transaction.Commit();
                            }

                            ContactedServer = true;
                        }
                    }
                }
            }

            // Get info about all the new catalog files
            var catalogFiles = session.QueryOver <CatalogFile>()
                               .Where(e => e.HasInformedServer == false)
                               .List <CatalogFile>();

            if (catalogFiles.Count() != 0)
            {
                foreach (var catalogFile in catalogFiles)
                {
                    using (var transaction = session.BeginTransaction())
                    {
                        if (Event.PostCatalogFile(catalogFile))
                        {
                            // Record that we sent this data to the server so we don't try sending it again
                            catalogFile.HasInformedServer = true;
                            session.Save(catalogFile);
                            transaction.Commit();
                        }
                    }

                    ContactedServer = true;
                }
            }

            if (!ContactedServer)
            {
                Log.Info("Posting heartbeat");
                dynamic eventResponse     = Event.PostHeartbeatEvent();
                int     avoidInfiniteLoop = 100;
                while (eventResponse != null)
                {
                    // Sanity check, want to avoid infinite loop
                    avoidInfiniteLoop--;
                    if (avoidInfiniteLoop < 0)
                    {
                        break;
                    }

                    eventResponse = HandleServerResponse(eventResponse);
                }
            }

            return(ContactedServer);
        }
Example #2
0
        /// <summary>
        /// This function is called when a new process is being started.  It return the decision if the process should be allowed to run.
        /// It stores some data in the DB about this executable (such as the computed hashes).
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="ExecutableId">Database ID for the executable</param>
        /// <returns>Decision on if the process should be allowed to run</returns>
        public static Decision DecideOnProcess(string filePath, out long ExecutableId)
        {
            Log.Info("Arbiter deciding on process");
            Decision      decision = Decision.ALLOW;
            List <Signer> signers  = null;

            ExecutableId = 0;  // TODO Must do something where there is an error in this function so we don't record that something with ExecutableID 0 happened

            try
            {
                filePath = CleanPath(filePath);
                Log.Info("Deciding on process: {0}", filePath);

                //
                // Check if we've seen this before
                //
                DateTime lastWriteTime = File.GetLastWriteTime(filePath);
                lastWriteTime = lastWriteTime.ToUniversalTime();

                var sessionFactory = Database.getSessionFactory();
                using (var session = sessionFactory.OpenSession())
                {
                    var exes = session.QueryOver <Executable>()
                               .Where(e => e.Path == filePath)
                               .And(e => e.LastWriteTime == lastWriteTime)
                               .List <Executable>();
                    if (exes.Count() != 0)
                    {
                        Executable foundExe = exes[0];
                        Log.Debug("Exe has been seen before");
                        ExecutableId = foundExe.Id;
                        // TODO need to use a rule engine
                        if (!foundExe.Trusted)
                        {
                            Log.Info("Deny it");
                            decision = Decision.DENY;
                        }
                        else
                        {
                            Log.Info("Allow it");
                        }
                        return(decision);
                    }
                }


                //
                // If we're here then this is new, so verify it
                //
                bool   isVerified = WinTrustVerify.WinTrust.Verify(filePath, out signers);
                string SignerName = "";
                if (isVerified)
                {
                    if (signers != null && signers.Count >= 1 && signers[0] != null)
                    {
                        SignerName = signers[0].Name;
                    }
                    Log.Info("File is signed by {0}", SignerName);
                }
                else
                {
                    Log.Info("File is not signed (or not trusted)");
                }

                // Compute hashes
                byte[] md5Hash, sha1Hash, sha256Hash;
                Helpers.ComputeHashes(filePath, out md5Hash, out sha1Hash, out sha256Hash);


                // Gather all this data
                var exe = new Executable
                {
                    Path          = filePath,
                    LastWriteTime = lastWriteTime,
                    LastSeen      = DateTime.UtcNow,
                    FirstSeen     = DateTime.UtcNow,
                    LastChecked   = DateTime.UtcNow,
                    Signed        = (signers != null),
                    Blocked       = false, // TODO Change this based on if we are in audit mode
                    Md5           = md5Hash,
                    Sha1          = sha1Hash,
                    Sha256        = sha256Hash,
                };


                //
                // Record this info to the DB
                //
                using (var session = sessionFactory.OpenSession())
                {
                    using (var transaction = session.BeginTransaction())
                    {
                        // I don't really need to check again, but I'm worried about a race
                        var exes = session.QueryOver <Executable>()
                                   .Where(e => e.Path == filePath)
                                   .And(e => e.LastWriteTime == lastWriteTime)
                                   .List <Executable>();
                        if (exes.Count() == 0)
                        {
                            // Ensure we don't add certs to the DB if they already exist there
                            if (signers != null)
                            {
                                foreach (var signer in signers)
                                {
                                    var certs = session.QueryOver <Certificate>()
                                                .Where(e => e.SerialNumber == signer.SigningCert.SerialNumber)
                                                .And(e => e.Issuer == signer.SigningCert.Issuer)
                                                .List <Certificate>();
                                    if (certs.Count() != 0)
                                    {
                                        signer.SigningCert = certs[0];
                                        break;
                                    }
                                }

                                Database.AddSignersToExe(exe, signers);
                            }

                            //
                            // Make a decision on it
                            //
                            decision    = MakeDecisionFromRules(exe);
                            exe.Trusted = (decision == Decision.ALLOW);

                            session.Save(exe);
                            transaction.Commit();

                            ExecutableId = exe.Id;
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Log.Exception(e, "Exception in DecideOnProcess");
            }

            return(FinalDecisionBasedOnMode(decision));
        }