/// <summary> /// Wraps the NetWkstaUserEnum API call in a timeout /// </summary> /// <param name="computer"></param> /// <returns></returns> private static async Task <List <Session> > GetLoggedOnUsersAPI(Computer computer) { var resumeHandle = 0; var workstationInfoType = typeof(WKSTA_USER_INFO_1); var ptrInfo = IntPtr.Zero; var entriesRead = 0; var sessionList = new List <Session>(); try { var task = Task.Run(() => NetWkstaUserEnum(computer.APIName, 1, out ptrInfo, -1, out entriesRead, out _, ref resumeHandle)); if (await Task.WhenAny(task, Task.Delay(10000)) != task) { if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Timeout", Task = "NetWkstaUserEnum" }); } return(sessionList); } var taskResult = task.Result; //Check the result of the task. 234 and 0 are both acceptable. if (taskResult != 0 && taskResult != 234) { if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = ((NetApiStatus)taskResult).ToString(), Task = "NetWkstaUserEnum" }); } return(sessionList); } var iterator = ptrInfo; if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Success", Task = "NetWkstaUserEnum" }); } for (var i = 0; i < entriesRead; i++) { var data = (WKSTA_USER_INFO_1)Marshal.PtrToStructure(iterator, workstationInfoType); iterator = (IntPtr)(iterator.ToInt64() + Marshal.SizeOf(workstationInfoType)); var domain = data.wkui1_logon_domain; var username = data.wkui1_username; //Remove local accounts if (domain.Equals(computer.SamAccountName, StringComparison.CurrentCultureIgnoreCase)) { continue; } //Remove blank accounts and computer accounts if (username.Trim() == "" || username.EndsWith("$") || username == "ANONYMOUS LOGON" || username == Options.Instance.CurrentUserName) { continue; } //Any domain with a space is unusable (ex: NT AUTHORITY, FONT DRIVER HOST) if (domain.Contains(" ")) { continue; } var(rSuccess, sid, _) = await ResolutionHelpers.ResolveAccountNameToSidAndType(username, domain); if (rSuccess) { sessionList.Add(new Session { UserId = sid, ComputerId = computer.ObjectIdentifier }); } else { sessionList.Add(new Session { UserId = $"{username}@{Helpers.NormalizeDomainName(domain)}".ToUpper(), ComputerId = computer.ObjectIdentifier }); } } return(sessionList); } finally { if (ptrInfo != IntPtr.Zero) { NetApiBufferFree(ptrInfo); } } }
/// <summary> /// Wraps the NetSessionEnum API call with a timeout and parses the results /// </summary> /// <param name="computer"></param> /// <returns></returns> private static async Task <List <Session> > GetNetSessions(Computer computer) { var resumeHandle = IntPtr.Zero; var sessionInfoType = typeof(SESSION_INFO_10); var entriesRead = 0; var ptrInfo = IntPtr.Zero; var sessionList = new List <Session>(); try { var task = Task.Run(() => NetSessionEnum(computer.APIName, null, null, 10, out ptrInfo, -1, out entriesRead, out _, ref resumeHandle)); //10 second timeout if (await Task.WhenAny(task, Task.Delay(10000)) != task) { if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Timeout", Task = "NetSessionEnum" }); } return(sessionList); } var taskResult = task.Result; if (taskResult != 0) { if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = ((NetApiStatus)taskResult).ToString(), Task = "NetSessionEnum" }); } return(sessionList); } var sessions = new SESSION_INFO_10[entriesRead]; var iterator = ptrInfo; for (var i = 0; i < entriesRead; i++) { sessions[i] = (SESSION_INFO_10)Marshal.PtrToStructure(iterator, sessionInfoType); iterator = (IntPtr)(iterator.ToInt64() + Marshal.SizeOf(sessionInfoType)); } if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Success", Task = "NetSessionEnum" }); } foreach (var session in sessions) { var sessionUsername = session.sesi10_username; var computerName = session.sesi10_cname; if (computerName == null) { continue; } string computerSid = null; //Filter out computer accounts, Anonymous Logon, empty users if (sessionUsername.EndsWith( "$") || sessionUsername.Trim() == "" || sessionUsername == "$" || sessionUsername == Options.Instance.CurrentUserName || sessionUsername == "ANONYMOUS LOGON") { continue; } //Remove leading backslashes if (computerName.StartsWith("\\")) { computerName = computerName.TrimStart('\\'); } //Remove empty sessions if (string.IsNullOrEmpty(computerName)) { continue; } //If the session is pointing to localhost, we already know what the SID of the computer is if (computerName.Equals("[::1]") || computerName.Equals("127.0.0.1")) { computerSid = computer.ObjectIdentifier; } //Try converting the computer name to a SID if we didn't already get it from a localhost computerSid = computerSid ?? await ResolutionHelpers.ResolveHostToSid(computerName, computer.Domain); //Try converting the username to a SID var searcher = Helpers.GetDirectorySearcher(computer.Domain); var sids = await searcher.LookupUserInGC(sessionUsername); if (sids?.Length > 0) { foreach (var sid in sids) { sessionList.Add(new Session { ComputerId = computerSid, UserId = sid }); } } else { var(success, sid, _) = await ResolutionHelpers.ResolveAccountNameToSidAndType(sessionUsername, computer.Domain); if (success) { sessionList.Add(new Session { ComputerId = computerSid, UserId = sid }); } else { sessionList.Add(new Session { ComputerId = computerSid, UserId = sessionUsername }); } } } return(sessionList); } finally { if (ptrInfo != IntPtr.Zero) { NetApiBufferFree(ptrInfo); } } }