Esempio n. 1
0
        public SessionMon()
        {
            // Catch up with existing sessions, if not already registered in DB
            var logprefix      = "SessionMon(): ";
            var activeSessions = WTS.ListSessions();

            using (var db = new LiteDatabase("Filename=" + Utils.MyPath("RdpMon.db") + ";utc=true"))
            {
                var table = db.GetCollection <Session>("Session");
                foreach (var wtsInfo in activeSessions)
                {
                    if (string.IsNullOrEmpty(wtsInfo.UserName))   // Skipping user-less sessions such as #0 and #65535
                    {
                        continue;
                    }
                    var sessionUID = wtsInfo.SessionUID();
                    var session    = table.FindById(sessionUID);
                    if (session == null)
                    {
                        Log(logprefix + "found active WTS session to catch up with: #" + wtsInfo.ID + "/" + wtsInfo.UserName);
                        session = new Session
                        {
                            SessionUid   = sessionUID,
                            WtsSessionId = wtsInfo.ID,
                            Start        = wtsInfo.LogonTime,
                            End          = null,
                            User         = wtsInfo.UserName,
                            Addr         = null, // Perhaps we could still try and obtain IP
                            Flags        = 0,
                        };
                        table.Insert(session);
                        DbProps.Set(db, "LastSessionChange", DateTime.UtcNow);
                    }
                }
            }
        }
Esempio n. 2
0
        public Addrs Aggregate(DateTime _fromUtc)
        {
            var logprefix = "Scan: ";

            Log(logprefix + "in");
            var timer = DateTime.UtcNow;

            try
            {
                var provider = "Security";
                using (var db = new LiteDatabase("Filename=" + Utils.MyPath("RdpMon.db") + ";utc=true"))
                {
                    var _lastDbModif = DbProps.Get(db, "LastAddrChange");
                    var lastDbModif  = (_lastDbModif != null ? (DateTime)_lastDbModif : DateTime.MinValue);
                    var fromUtc      = (_fromUtc == DateTime.MinValue ? lastDbModif : _fromUtc);
                    //var fromLocal = fromUtc.ToLocalTime();
                    var query = "*[" +
                                "(System/EventID=" + SuccessEvtId.ToString() + " or " + "System/EventID=" + FailureEvtId.ToString() + ")" +
                                " and " +
                                "System[TimeCreated[@SystemTime>'" + fromUtc.ToString("yyyy-MM-dd") + "T" + fromUtc.ToString("HH:mm:ss") + ".000000000Z" + "']]" +
                                "]";

                    // Skip if DB hasn't changed since fromUtc
                    if (lastDbModif != null && lastDbModif < fromUtc)
                    {
                        Log(logprefix + "out: DB unchanged, skipping");
                        iteration++;
                        return(addrs);
                    }

                    var addrTable = db.GetCollection <Addr>("Addr");
                    if (updateDb)
                    {
                        var eventsQuery = new EventLogQuery(provider, PathType.LogName, query);
                        if (dbg)
                        {
                            var rand    = new Random(Environment.TickCount);
                            var dbgRand = true;
                            for (int i = 0; i < 200; i++)
                            {
                                var success = ((dbgRand ? rand.Next(200) : i) > 400);
                                var ip      = string.Format("{0}.{1}.{2}.{3}", 132, 154, 255, (dbgRand ? rand.Next(50) : i) + 1);
                                var now     = DateTime.UtcNow;
                                var utcTime = dbgRand ? now.Subtract(TimeSpan.FromMinutes(rand.Next(60)))
                                                      : new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0);
                                var userName = "******" + (dbgRand ? rand.Next(9) : i) + 1;
                                if (utcTime > fromUtc)
                                {
                                    addrs.Aggregate(addrTable, ip, utcTime, success, userName);
                                }
                            }
                        }
                        else
                        {
                            var logReader = new EventLogReader(eventsQuery);
                            for (var evt = logReader.ReadEvent(); evt != null; evt = logReader.ReadEvent())
                            {
                                addrs.Aggregate(addrTable, evt, dbg);
                            }
                        }
                        if (addrs.lastDbChange != null)
                        {
                            DbProps.Set(db, "LastAddrChange", DateTime.UtcNow);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log(logprefix + "* exception: " + ex.ToString());
            }

            var perfDuration = DateTime.UtcNow.Subtract(timer);

            Log(logprefix + "out: " + addrs.Items.Count.ToString() + " addrs found, took " + perfDuration.TotalSeconds + " seconds");
            iteration++;
            return(addrs);
        }
Esempio n. 3
0
        void OnNewProcessReady(uint pid, ProcessInfo processInfo)
        {
            var logprefix = "ProcessMon.OnNewProcessReady: ";

            try
            {
                var shortName    = processInfo.ShortName;
                var wtsSessionId = processInfo.WtsSessionId;
                var parentPid    = processInfo.ParentPid;
                logprefix = "ProcessMon.OnNewProcessReady(" + pid + ", " + shortName + ", #" + wtsSessionId + "): ";
                var normalizedPath = NormalizePath(processInfo.FullFileName);
                Log(logprefix + normalizedPath + ", parent=" + parentPid.ToString());
                using (var db = new LiteDatabase("Filename=" + Utils.MyPath("RdpMon.db") + ";utc=true"))
                {
                    var hash = Utils.FileHashSHA256(processInfo.FullFileName);
                    if (hash != null)
                    {
                        var  wtsInfo    = WTS.QuerySessionInfo((int)wtsSessionId);
                        long sessionUid = 0;
                        if (wtsInfo != null)
                        {
                            sessionUid = Session.GetSessionUid(wtsSessionId, wtsInfo.LogonTime);
                        }
                        else
                        {
                            Log(logprefix + "* failed finding session #" + wtsSessionId);
                        }
                        var table    = db.GetCollection <Cameyo.RdpMon.Process>("Process");
                        var item     = table.FindById(hash);
                        var execInfo = new ExecInfo
                        {
                            SessionUid = sessionUid,
                            Flags      = 0,
                            Pid        = pid,
                            ParentPid  = parentPid,
                            Start      = DateTime.UtcNow,
                        };
                        if (item != null)
                        {
                            var _list = item.ExecInfos.ToList();
                            _list.Add(execInfo);
                            item.ExecInfos = _list.ToArray();
                            table.Update(item);
                        }
                        else if (item == null)
                        {
                            item           = new Process();
                            item.ExecInfos = new [] { execInfo };
                            item.ProcessId = hash;
                            item.HashType  = 1;
                            item.Flags     = 0;
                            item.Path      = normalizedPath;
                            //item.Start = DateTime.UtcNow;
                            table.Insert(item);
                            DbProps.Set(db, "LastProcessChange", DateTime.UtcNow);
                        }
                    }
                    else
                    {
                        Log(logprefix + "failed hashing file");
                    }
                }
            }
            catch (Exception ex)
            {
                Log(logprefix + "* exception: " + ex.ToString());
            }
        }
Esempio n. 4
0
        void RefreshSessionsLV(bool initialLoad, List <WTS.SessionInfo> activeSessions)
        {
            //var logprefix = "RefreshSessionsLV: ";
            var startedLvUpdate = false;
            var lv = sessionsLv;

            // Initial load or update?
            if (initialLoad)
            {
                lastSessionsRefresh = DateTime.MinValue;
                startedLvUpdate     = true;
                lv.BeginUpdate();
                lv.ListViewItemSorter = null;
                lv.Items.Clear();
            }
            var now = DateTime.UtcNow;

            using (var db = new LiteDatabase("Filename=" + Utils.MyPath("RdpMon.db") + ";utc=true"))
            {
                var _lastDbModif = DbProps.Get(db, "LastSessionChange");
                var lastDbModif  = (_lastDbModif != null ? (DateTime)_lastDbModif : DateTime.MinValue);
                var table        = db.GetCollection <Session>("Session");
                foreach (var dbSession in table.FindAll())
                {
                    if (dbSession.Start < lastSessionsRefresh && dbSession.End != null)
                    {
                        if (DateTime.UtcNow.Subtract(dbSession.End.Value) < TimeSpan.FromSeconds(60) &&
                            FindSessionLvItem(dbSession.SessionUid, out var lvi))
                        {
                            // Update just-ended session
                            lvi.SubItems[ColSessionState.DisplayIndex].Text = "Ended";
                            lvi.SubItems[ColSessionEnded.DisplayIndex].Text = (dbSession.End != null ? dbSession.End.Value.ToLocalTime().ToString("MM/dd HH:mm:ss") : "");
                            lvi.ImageIndex = -1;
                        }
                        continue;
                    }

                    var equivalentActiveSession = GetEquivalentActiveSession(dbSession, activeSessions);
                    if (!startedLvUpdate)
                    {
                        startedLvUpdate = true;
                        lv.BeginUpdate();
                        lv.ListViewItemSorter = null;
                    }

                    var existingFound = false;
                    if (equivalentActiveSession != null)
                    {
                        if (FindSessionLvItem(dbSession.SessionUid, out var lvi))
                        {
                            lvi.SubItems[ColSessionStarted.DisplayIndex].Text = dbSession.Start.ToLocalTime().ToString("MM/dd HH:mm:ss");
                            lvi.SubItems[ColSessionState.DisplayIndex].Text   = equivalentActiveSession.StateStr();
                            lvi.Tag       = dbSession;
                            existingFound = true;
                        }
                    }
                    if (existingFound)
                    {
                        continue;
                    }

                    // Add / update in list
                    {
                        var adding = false;
                        if (!FindSessionLvItem(dbSession.SessionUid, out var lvi)) // Special case: sometimes LvItem may be found in list if the DB has missed its Ended time (i.e. if the service was down while the session ended)
                        {
                            // Usual case
                            lvi = new ListViewItem();
                            lvi.SubItems.AddRange(new[] { "", "", "", "", "", "", "" });
                            adding = true;
                        }

                        lvi.SubItems[ColWtsSessionId.DisplayIndex].Text   = dbSession.WtsSessionId.ToString();
                        lvi.SubItems[ColSessionUser.DisplayIndex].Text    = (dbSession.User ?? "").ToString();
                        lvi.SubItems[ColSessionStarted.DisplayIndex].Text = dbSession.Start.ToLocalTime().ToString("MM/dd HH:mm:ss");
                        if (dbSession.End != null)
                        {
                            lvi.SubItems[ColSessionState.DisplayIndex].Text = "Ended";
                        }
                        if (equivalentActiveSession != null)
                        {
                            lvi.ImageIndex = 1;
                            lvi.SubItems[ColSessionEnded.DisplayIndex].Text = "ongoing";
                        }
                        else
                        {
                            lvi.SubItems[ColSessionEnded.DisplayIndex].Text = (dbSession.End != null ? dbSession.End.Value.ToLocalTime().ToString("MM/dd HH:mm:ss") : "");
                        }

                        lvi.SubItems[ColSessionAddr.DisplayIndex].Text = (dbSession.Addr == "127.0.0.1" ? "localhost" : dbSession.Addr);
                        lvi.Tag = dbSession;
                        if (adding)
                        {
                            lv.Items.Add(lvi);
                        }
                    }
                }
            }
            if (startedLvUpdate)
            {
                lv.ListViewItemSorter = sessionsSorter;
                lv.Sort();
                lv.EndUpdate();
                lv.ListViewItemSorter = null;
            }
            lastSessionsRefresh = now;
        }
Esempio n. 5
0
        public void OnSessionChange(SessionChangeDescription sessionChange)
        {
            var wtsSessionId = sessionChange.SessionId;
            var logprefix    = "SessionMon #" + wtsSessionId.ToString("D2") + " [" + sessionChange.Reason.ToString() + "]: ";

            //EventLog.WriteEntry("OnSessionChange", changeDescription.Reason.ToString() + " Session ID: " + changeDescription.SessionId.ToString());
            Log(logprefix + "@");
            WTS.SessionInfo wtsInfo;
            var             utcNow = DateTime.UtcNow;

            try
            {
                switch (sessionChange.Reason)
                {
                // SessionLogon
                case SessionChangeReason.SessionLogon:
                    Thread.Sleep(3000 * 1);       // Wait for session to be logged in event log
                    var provider = "Microsoft-Windows-TerminalServices-LocalSessionManager/Operational";
                    var fromUtc  = utcNow.Subtract(TimeSpan.FromMinutes(1));
                    //var toUtc = utcNow.Add(TimeSpan.FromMinutes(1));
                    var query = "*[" +
                                "(System/EventID=21 and UserData/EventXML/SessionID=" + wtsSessionId + ")" +
                                " and " +
                                "System[TimeCreated[@SystemTime>'" + fromUtc.ToString("yyyy-MM-dd") + "T" + fromUtc.ToString("HH:mm:ss") + ".000000000Z" + "']]" +

                                /*" and " +
                                 * "System[TimeCreated[@SystemTime<'" + toUtc.ToString("yyyy-MM-dd") + "T" + toUtc.ToString("HH:mm:ss") + ".000000000Z" + "']] " +*/
                                "]";
                    var eventsQuery = new EventLogQuery(provider, PathType.LogName, query);
                    {
                        var logReader = new EventLogReader(eventsQuery);
                        for (var evt = logReader.ReadEvent(); evt != null; evt = logReader.ReadEvent())
                        {
                            var xmldoc = new XmlDocument();
                            var xml    = evt.ToXml();
                            var ns     = new XmlNamespaceManager(xmldoc.NameTable);
                            //ns.AddNamespace("ns", "http://schemas.microsoft.com/win/2004/08/events/event");
                            ns.AddNamespace("ns", "Event_NS");
                            xmldoc.LoadXml(xml);
                            var nodes = xmldoc.SelectNodes("//ns:*", ns);
                            if (nodes != null)
                            {
                                int    _wtsSessionId = -1;
                                string user = null, addr = null;
                                for (int i = 0; i < nodes.Count; i++)
                                {
                                    if (nodes[i].Name == "SessionID")
                                    {
                                        int.TryParse(nodes[i].InnerText, out _wtsSessionId);
                                    }
                                    if (nodes[i].Name == "User")
                                    {
                                        user = nodes[i].InnerText;
                                    }
                                    if (nodes[i].Name == "Address")
                                    {
                                        addr = nodes[i].InnerText;
                                    }
                                }
                                Log(logprefix + "session=" + _wtsSessionId + ", user="******", addr=" + addr);
                                if (_wtsSessionId != -1)
                                {
                                    wtsInfo = WTS.QuerySessionInfo(_wtsSessionId);
                                    if (wtsInfo != null)
                                    {
                                        using (var db = new LiteDatabase("Filename=" + Utils.MyPath("RdpMon.db") + ";utc=true"))
                                        {
                                            var table   = db.GetCollection <Session>("Session");
                                            var session = new Session
                                            {
                                                SessionUid   = Session.GetSessionUid(_wtsSessionId, wtsInfo.LogonTime),
                                                WtsSessionId = _wtsSessionId,
                                                Start        = wtsInfo.LogonTime,
                                                End          = null,
                                                User         = wtsInfo.UserName,
                                                Addr         = addr,
                                                Flags        = 0,
                                            };
                                            table.Insert(session);
                                            DbProps.Set(db, "LastSessionChange", DateTime.UtcNow);
                                        }
                                    }
                                    else
                                    {
                                        Log(logprefix + "* could not find WTS session #" + _wtsSessionId);
                                    }
                                }
                                else
                                {
                                    Log(logprefix + "* could not parse session ID from event log: " + xml);
                                }
                            }
                            else
                            {
                                Log(logprefix + "* could not read event log: " + xml);
                            }
                        }
                    }
                    break;

                // SessionLogoff
                case SessionChangeReason.SessionLogoff:
                    wtsInfo = WTS.QuerySessionInfo(wtsSessionId);
                    if (wtsInfo != null)
                    {
                        using (var db = new LiteDatabase("Filename=" + Utils.MyPath("RdpMon.db") + ";utc=true"))
                        {
                            var table      = db.GetCollection <Session>("Session");
                            var sessionUID = Session.GetSessionUid(wtsSessionId, wtsInfo.LogonTime);
                            var session    = table.FindById(sessionUID);
                            if (session != null)
                            {
                                session.End = DateTime.UtcNow;
                                table.Update(session);
                            }
                            DbProps.Set(db, "LastSessionChange", DateTime.UtcNow);
                        }
                    }
                    else
                    {
                        Log(logprefix + "* could not find WTS session #" + wtsSessionId);
                    }
                    break;

                // Other events
                default:
                    break;
                }
            }
            catch (Exception ex)
            {
                Log(logprefix + "* exception: " + ex.ToString());
            }
        }