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); } } } }
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); }
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()); } }
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; }
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()); } }