private void RunAccessCheckHandles(IEnumerable <TokenEntry> tokens) { var type_filter = GetTypeFilter(); using (NtToken process_token = NtToken.OpenProcessToken()) { if (!process_token.SetPrivilege(TokenPrivilegeValue.SeDebugPrivilege, PrivilegeAttributes.Enabled)) { WriteWarning("Current process doesn't have SeDebugPrivilege, results may be inaccurate"); } } if (type_filter.Count == 0) { WriteWarning("Checking handle access without any type filtering can hang. Perhaps specify the types using -TypeFilter."); } HashSet <ulong> checked_objects = new HashSet <ulong>(); var handles = NtSystemInfo.GetHandles(-1, false).Where(h => IsTypeFiltered(h.ObjectType, type_filter)).GroupBy(h => h.ProcessId); foreach (var group in handles) { if (Stopping) { return; } using (var proc = NtProcess.Open(group.Key, ProcessAccessRights.DupHandle, false)) { if (proc.IsSuccess) { CheckHandles(tokens, type_filter, checked_objects, proc.Result, group); } } } }
static string GetProcessName(int process_id, bool verbose) { var image_path = NtSystemInfo.GetProcessIdImagePath(process_id, false); if (image_path.IsSuccess) { return(verbose ? image_path.Result : Path.GetFileName(image_path.Result)); } using (var process = NtProcess.Open(process_id, ProcessAccessRights.QueryLimitedInformation, false)) { if (process.IsSuccess) { if (verbose) { return(process.Result.FullPath); } else { return(process.Result.Name); } } else { try { return(Process.GetProcessById(process_id).ProcessName); } catch (ArgumentException) { } } return("Unknown"); } }
static void Main(string[] args) { bool verbose = false; if (args.Length > 0 && args[0] == "-verbose") { verbose = true; } try { if (!NtToken.EnableDebugPrivilege()) { Console.WriteLine("WARNING: Can't enable debug privilege. Some zombies may not be found. Run as admin for full results."); } var zombies = GetZombieProcessObjectAddress(); var flattenList = zombies.Values.ToList(); var q = from x in flattenList group x by x into g let count = g.Count() orderby count descending select new { Value = g.Key, Count = count }; Dictionary <string, int> orphaned = q.ToDictionary(x => x.Value, x => x.Count); Console.Write("{0} total zombie processes.", zombies.Count); if (zombies.Count == 0) { Console.WriteLine("No zombies found. Maybe all software is working correctly, but I doubt it. " + "More likely the zombie counting process failed for some reason. Please try again."); } // Create a list to store the pids of process that hold zombies, a list of zombie handles, // a count of the zombies. The count is first for sorting. List <Tuple <int, int, HandleList> > count_and_pid = new List <Tuple <int, int, HandleList> >(); foreach (var group in NtSystemInfo.GetHandles(-1, false).GroupBy(h => h.ProcessId)) { var total = group.Where(h => zombies.ContainsKey(h.Object)); int count = total.Count(); if (count > 0) { count_and_pid.Add(new Tuple <int, int, HandleList>(count, group.Key, total)); } } // Print the processes holding handles to zombies, sorted by zombie count. count_and_pid.Sort(); count_and_pid.Reverse(); int total_count_zombies = 0; foreach (Tuple <int, int, HandleList> buggy_process in count_and_pid) { total_count_zombies += buggy_process.Item1; } int total_count_orphans = zombies.Count - total_count_zombies; Console.WriteLine(" ({0} {1} and {2} {3})", total_count_zombies, ZombiePluralized(total_count_zombies), total_count_orphans, OrphanPluralized(total_count_orphans)); foreach (Tuple <int, int, HandleList> buggy_process in count_and_pid) { int count_by = buggy_process.Item1; int pid = buggy_process.Item2; HandleList total = buggy_process.Item3; Console.WriteLine(" {0} {1} held by {2}({3})", count_by, ZombiePluralized(count_by), GetProcessName(pid, verbose), pid); var names = total.GroupBy(h => zombies[h.Object], StringComparer.CurrentCultureIgnoreCase); List <Tuple <int, string> > zombies_from_process = new List <Tuple <int, string> >(); foreach (var name in names) { int slash_index = name.Key.LastIndexOf('\\'); if (verbose) { slash_index = -1; } string process_name = name.Key.Substring(slash_index + 1); zombies_from_process.Add(new Tuple <int, string>(name.Count(), process_name)); if (orphaned.ContainsKey(name.Key)) { orphaned[name.Key] = orphaned[name.Key] - name.Count(); } } // Print the processes being held as zombies, sorted by count. zombies_from_process.Sort(); zombies_from_process.Reverse(); foreach (var zombie_process in zombies_from_process) { int count_of = zombie_process.Item1; string process_name = zombie_process.Item2; Console.WriteLine(" {0} {1} of {2}", count_of, ZombiePluralized(count_of), process_name); } } Console.WriteLine(" {0} {1}", total_count_orphans, OrphanPluralized(total_count_orphans)); foreach (var item in orphaned) { int slash_index = item.Key.LastIndexOf('\\'); if (verbose) { slash_index = -1; } string process_name = item.Key.Substring(slash_index + 1); if (item.Value != 0) { Console.WriteLine(" {0} {1} of {2}", item.Value, OrphanPluralized(item.Value), process_name); } } if (!verbose) { Console.WriteLine("Pass -verbose to get full zombie names."); } } catch (Exception ex) { Console.WriteLine(ex.Message); } int[] pids = new int[3]; if (GetConsoleProcessList(pids, 3) == 1) { Console.Write("Press any key to continue"); Console.ReadKey(); } }
static void Main(string[] args) { try { bool show_help = false; HashSet <string> typeFilter = new HashSet <string>(); HashSet <int> pidFilter = new HashSet <int>(); HashSet <string> nameFilter = new HashSet <string>(); bool noquery = false; GroupingMode mode = GroupingMode.Pid; ShareMode shareMode = ShareMode.None; bool showsd = false; PrintDeprecationWarning(); OptionSet opts = new OptionSet() { { "t|type=", "An object type to filter on, can be repeated", v => typeFilter.Add(v.Trim().ToLower()) }, { "p|pid=", "A PID to filter on, can be repeated", v => pidFilter.Add(int.Parse(v.Trim())) }, { "n|name=", "Specify a process by name", v => nameFilter.Add(v.ToLower()) }, { "q|noquery", "Don't query for names/typenames", v => noquery = v != null }, { "g|group=", "Specify a grouping, defaults to pid, can be object,name,type", v => mode = (GroupingMode)Enum.Parse(typeof(GroupingMode), v, true) }, { "s|share=", "When grouping, filter on shared, can be none,partial or all", v => shareMode = (ShareMode)Enum.Parse(typeof(ShareMode), v, true) }, { "sd", "Display the security descriptor associated with the kernel object", v => showsd = v != null }, { "h|help", "show this message and exit", v => show_help = v != null }, }; opts.Parse(args); if (show_help) { ShowHelp(opts); } else { IEnumerable <NtProcess> filtered = NtProcess.GetProcesses(ProcessAccessRights.MaximumAllowed); if (pidFilter.Count > 0) { filtered = filtered.Where(ps => pidFilter.Contains(ps.ProcessId)); } if (nameFilter.Count > 0) { filtered = filtered.Where(ps => nameFilter.Contains(ps.FullPath, StringComparer.OrdinalIgnoreCase)); } HashSet <int> pids = new HashSet <int>(filtered.Select(process => process.ProcessId)); Dictionary <int, string> pidToName = filtered.ToDictionary(pk => pk.ProcessId, pv => pv.FullPath); List <NtHandle> totalHandles = new List <NtHandle>(); foreach (int pid in pids) { if (pid == Process.GetCurrentProcess().Id) { continue; } IEnumerable <NtHandle> handles = NtSystemInfo.GetHandles(pid, true).Where(ent => (typeFilter.Count == 0) || typeFilter.Contains(ent.ObjectType.ToLower())); totalHandles.AddRange(handles); if (mode == GroupingMode.Pid) { Console.WriteLine("Process ID: {0} - Name: {1}", pid, pidToName[pid]); foreach (NtHandle ent in handles) { Console.WriteLine("{0:X04}: {1:X016} {2:X08} {3,20} {4}", ent.Handle, ent.Object, ent.GrantedAccess, ent.ObjectType, ent.Name); if (showsd && ent.SecurityDescriptor != null) { Console.WriteLine("SDDL: {0}", ent.SecurityDescriptor.ToSddl()); } } Console.WriteLine(); } } switch (mode) { case GroupingMode.Type: PrintGrouping(totalHandles.GroupBy(f => f.ObjectType), pidToName, k => $"Type: {k}", e => $"{e.Object:X08} {e.GrantedAccess:X08} {e.Name}", shareMode, pids.Count, showsd); break; case GroupingMode.Object: PrintGrouping(totalHandles.GroupBy(f => f.Object), pidToName, k => $"Object: {k:X08}", e => $"{e.ObjectType,20} {e.GrantedAccess:X08} {e.Name}", shareMode, pids.Count, showsd); break; case GroupingMode.Name: PrintGrouping(totalHandles.GroupBy(f => f.ObjectType), pidToName, k => $"Name: {k:X08}", e => $"{e.Object:X08} {e.Name,20} {e.GrantedAccess:X08} {e.GrantedAccess}", shareMode, pids.Count, showsd); break; } } } catch (Exception ex) { Console.WriteLine(ex); } }
private void btnRefreshHandles_Click(object sender, EventArgs e) { ClearList(listViewHandles); int current_pid = Process.GetCurrentProcess().Id; NtToken.EnableDebugPrivilege(); List <ListViewItem> items = new List <ListViewItem>(); foreach (var group in NtSystemInfo.GetHandles() .Where(h => h.ProcessId != current_pid && h.ObjectType.Equals("token", StringComparison.OrdinalIgnoreCase)) .GroupBy(h => h.ProcessId)) { using (var proc = NtProcess.Open(group.Key, ProcessAccessRights.DupHandle | ProcessAccessRights.QueryLimitedInformation, false)) { if (!proc.IsSuccess) { continue; } foreach (NtHandle handle in group) { using (var token_result = NtToken.DuplicateFrom(proc.Result, new IntPtr(handle.Handle), TokenAccessRights.None, DuplicateObjectOptions.SameAccess, false)) { if (!token_result.IsSuccess) { continue; } NtToken token = token_result.Result; ListViewItem item = new ListViewItem(handle.ProcessId.ToString()); item.SubItems.Add(proc.Result.Name); item.SubItems.Add($"0x{handle.Handle:X}"); if (!token.IsAccessGranted(TokenAccessRights.Query)) { item.SubItems.Add("UNKNOWN"); item.SubItems.Add("UNKNOWN"); item.SubItems.Add("UNKNOWN"); item.SubItems.Add("UNKNOWN"); item.SubItems.Add("UNKNOWN"); item.SubItems.Add("UNKNOWN"); } else { item.SubItems.Add(token.User.ToString()); item.SubItems.Add(token.IntegrityLevel.ToString()); string restricted = token.Restricted.ToString(); if (token.WriteRestricted) { restricted = "Write"; } item.SubItems.Add(restricted); item.SubItems.Add(token.AppContainer.ToString()); item.SubItems.Add(token.TokenType.ToString()); item.SubItems.Add(token.ImpersonationLevel.ToString()); } item.Tag = token.Duplicate(); items.Add(item); } } } } listViewHandles.Items.AddRange(items.ToArray()); ResizeColumns(listViewHandles); }
static void Main(string[] args) { try { bool show_help = false; string typeFilter = ""; bool show_all = false; OptionSet p = new OptionSet() { { "t|type=", "An object type to filter on", v => typeFilter = v.Trim() }, { "a|all", "Show all handles shared by at least one process", v => show_all = v != null }, { "h|help", "show this message and exit", v => show_help = v != null }, }; List <int> pids = p.Parse(args).Select(e => int.Parse(e)).ToList(); if (show_help || pids.Count < 2) { ShowHelp(p); } else { HashSet <IntPtr> sharedObjects = new HashSet <IntPtr>(); Dictionary <ulong, List <NtHandle> > entries = new Dictionary <ulong, List <NtHandle> >(); foreach (int pid in pids) { foreach (NtHandle entry in NtSystemInfo.GetHandles(pid, true)) { if (!entries.ContainsKey(entry.Object)) { entries[entry.Object] = new List <NtHandle>(); } entries[entry.Object].Add(entry); } } int limit = show_all ? 2 : pids.Count; var output = entries.Where(x => x.Value.GroupBy(y => y.ProcessId).Count() >= limit); foreach (KeyValuePair <ulong, List <NtHandle> > pair in output) { if (String.IsNullOrWhiteSpace(typeFilter) || pair.Value[0].ObjectType.Equals(typeFilter, StringComparison.OrdinalIgnoreCase)) { Console.WriteLine("{0:X} {1} {2}", pair.Key, pair.Value[0].ObjectType, GetObjectName(pair.Value)); foreach (NtHandle entry in pair.Value) { Console.WriteLine("\t{0}/0x{0:X} {1}/0x{1:X} 0x{2:X08}", entry.ProcessId, entry.Handle, entry.GrantedAccess); } } } } } catch (Exception ex) { Console.WriteLine(ex); } }
static void Main(string[] args) { try { int pid = NtProcess.Current.ProcessId; bool show_help = false; bool print_sddl = false; OptionSet opts = new OptionSet() { { "p|pid=", "Specify a PID of a process for access check.", v => pid = int.Parse(v.Trim()) }, { "sddl", "Print SDDL security descriptor.", v => print_sddl = v != null }, { "h|help", "show this message and exit", v => show_help = v != null }, }; HashSet <int> pids = new HashSet <int>(opts.Parse(args).Select(a => int.Parse(a))); if (show_help) { ShowHelp(opts); return; } Dictionary <string, string> ports = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); NtToken.EnableDebugPrivilege(); using (NtToken token = NtToken.OpenProcessToken(pid)) { IEnumerable <NtHandle> handles = NtSystemInfo.GetHandles(-1, false); HashSet <ulong> checked_objects = new HashSet <ulong>(); if (pids.Count > 0) { handles = handles.Where(h => pids.Contains(h.ProcessId)); } handles = handles.Where(h => h.ObjectType.Equals("ALPC Port", StringComparison.OrdinalIgnoreCase)); Dictionary <int, NtProcess> pid_to_process = new Dictionary <int, NtProcess>(); foreach (NtHandle handle in handles.Where(h => h.GrantedAccess.IsAccessGranted(GenericAccessRights.ReadControl))) { if (!pid_to_process.ContainsKey(handle.ProcessId)) { var result = NtProcess.Open(handle.ProcessId, ProcessAccessRights.QueryLimitedInformation | ProcessAccessRights.DupHandle, false); pid_to_process[handle.ProcessId] = result.IsSuccess ? result.Result : null; } NtProcess proc = pid_to_process[handle.ProcessId]; if (proc == null) { continue; } try { using (NtAlpc obj = NtAlpc.DuplicateFrom(proc, new IntPtr(handle.Handle))) { string name = obj.FullPath; // We only care about named ALPC ports. if (String.IsNullOrEmpty(name)) { continue; } if (ports.ContainsKey(name)) { continue; } SecurityDescriptor sd = obj.SecurityDescriptor; AccessMask granted_access = NtSecurity.GetAllowedAccess(sd, token, AlpcAccessRights.Connect, obj.NtType.GenericMapping); if (granted_access.IsEmpty) { continue; } ports.Add(name, sd.ToSddl()); } } catch (NtException) { } } } foreach (var pair in ports.OrderBy(p => p.Key)) { Console.WriteLine(pair.Key); if (print_sddl) { Console.WriteLine("SDDL: {0}", pair.Value); } } } catch (Exception ex) { Console.Error.WriteLine(ex.Message); } }
static void Main(string[] args) { bool verbose = false; if (args.Length > 0 && args[0] == "-verbose") { verbose = true; } try { if (!NtToken.EnableDebugPrivilege()) { Console.WriteLine("WARNING: Can't enable debug privilege. Some process names may be missing."); } var zombies = GetZombieProcessObjectAddress(); Console.WriteLine("{0} total zombie processes.", zombies.Count); if (zombies.Count == 0) { Console.WriteLine("No zombies found. Maybe all software is working correctly, but I doubt it. " + "More likely the zombie counting process failed for some reason. Please try again."); } // Create a list to store the pids of process that hold zombies, a list of zombie handles, // a count of the zombies. The count is first for sorting. List <Tuple <int, int, HandleList> > count_and_pid = new List <Tuple <int, int, HandleList> >(); foreach (var group in NtSystemInfo.GetHandles(-1, false).GroupBy(h => h.ProcessId)) { var total = group.Where(h => zombies.ContainsKey(h.Object)); int count = total.Count(); if (count > 0) { count_and_pid.Add(new Tuple <int, int, HandleList>(count, group.Key, total)); } } // Print the processes holding handles to zombies, sorted by zombie count. count_and_pid.Sort(); count_and_pid.Reverse(); foreach (Tuple <int, int, HandleList> buggy_process in count_and_pid) { int count_by = buggy_process.Item1; int pid = buggy_process.Item2; HandleList total = buggy_process.Item3; Console.WriteLine(" {0} {1} held by {2}({3})", count_by, ZombiePluralized(count_by), GetProcessName(pid, verbose), pid); var names = total.GroupBy(h => zombies[h.Object], StringComparer.CurrentCultureIgnoreCase); List <Tuple <int, string> > zombies_from_process = new List <Tuple <int, string> >(); foreach (var name in names) { int slash_index = name.Key.LastIndexOf('\\'); if (verbose) { slash_index = -1; } string process_name = name.Key.Substring(slash_index + 1); zombies_from_process.Add(new Tuple <int, string>(name.Count(), process_name)); } // Print the processes being held as zombies, sorted by count. zombies_from_process.Sort(); zombies_from_process.Reverse(); foreach (var zombie_process in zombies_from_process) { int count_of = zombie_process.Item1; string process_name = zombie_process.Item2; Console.WriteLine(" {0} {1} of {2}", count_of, ZombiePluralized(count_of), process_name); } } if (!verbose) { Console.WriteLine("Pass -verbose to get full zombie names."); } } catch (Exception ex) { Console.WriteLine(ex.Message); } }
internal RpcServerProcessInformation(int process_id, int session_id) { ProcessId = process_id; SessionId = session_id; ImagePath = NtSystemInfo.GetProcessIdImagePath(process_id, false).GetResultOrDefault(string.Empty); }
/// <summary> /// Overridden ProcessRecord method. /// </summary> protected override void ProcessRecord() { WriteObject(NtSystemInfo.GetHandles(ProcessId, !NoQuery), true); }
/// <summary> /// Get a list of all RPC ALPC servers. /// </summary> /// <remarks>This works by discovering any server ALPC ports owned by the process and querying for interfaces.</remarks> /// <returns>The list of RPC ALPC servers.</returns> public static IEnumerable <RpcAlpcServer> GetAlpcServers() { return(GetAlpcServersInternal(NtSystemInfo.GetHandles()).ToCached()); }
/// <summary> /// Get RPC ALPC servers for a specific process. /// </summary> /// <param name="process_id">The ID of the process.</param> /// <returns>The list of RPC ALPC servers.</returns> public static IEnumerable <RpcAlpcServer> GetAlpcServers(int process_id) { return(GetAlpcServersInternal(NtSystemInfo.GetHandles(process_id, true)).ToCached()); }
static void Main(string[] args) { bool verbose = false; if (args.Length > 0 && args[0] == "-verbose") { verbose = true; } try { if (!NtToken.EnableDebugPrivilege()) { Console.WriteLine("WARNING: Can't enable debug privilege. Some zombies may not be found. Run as admin for full results."); } var zombies = GetZombieObjectAddress(); Console.WriteLine("{0} total zombie processes.", zombies.Values.Count(h => !h.IsThread)); Console.WriteLine("{0} total zombie threads.", zombies.Values.Count(h => h.IsThread)); if (zombies.Count == 0) { Console.WriteLine("No zombies found. Maybe all software is working correctly, but I doubt it. " + "More likely the zombie counting process failed for some reason. Please try again."); } // Create a list to store the pids of process that hold zombies, a list of zombie handles, // a count of the zombies. The count is first for sorting. List <Tuple <int, int, List <ZombieHandle> > > count_and_pid = new List <Tuple <int, int, List <ZombieHandle> > >(); foreach (var group in NtSystemInfo.GetHandles(-1, false).GroupBy(h => h.ProcessId)) { var total = group.Where(h => zombies.ContainsKey(h.Object)).Select(h => zombies[h.Object]).ToList(); int count = total.Select(h => h.ProcessId).Distinct().Count(); if (count > 0) { count_and_pid.Add(Tuple.Create(count, group.Key, total)); } } // Print the processes holding handles to zombies, sorted by zombie count. count_and_pid.Sort(); count_and_pid.Reverse(); foreach (var buggy_process in count_and_pid) { int count_by = buggy_process.Item1; int pid = buggy_process.Item2; var total = buggy_process.Item3; Console.WriteLine(" {0} {1} held by {2}({3})", count_by, ZombiePluralized(count_by), GetProcessName(pid, verbose), pid); var names = total.GroupBy(h => h.ProcessPath, StringComparer.CurrentCultureIgnoreCase); var zombies_from_process = new List <Tuple <int, string, int, int> >(); foreach (var name in names) { int slash_index = name.Key.LastIndexOf('\\'); if (verbose) { slash_index = -1; } string process_name = name.Key.Substring(slash_index + 1); int process_count = name.Count(h => !h.IsThread); int thread_count = name.Count(h => h.IsThread); int unique_process = name.Select(h => h.ProcessId).Distinct().Count(); zombies_from_process.Add(Tuple.Create(unique_process, process_name, process_count, thread_count)); } // Print the processes being held as zombies, sorted by count. zombies_from_process.Sort(); zombies_from_process.Reverse(); foreach (var zombie_process in zombies_from_process) { int total_count = zombie_process.Item1; string process_name = zombie_process.Item2; int process_count = zombie_process.Item3; int thread_count = zombie_process.Item4; Console.WriteLine(" {0} {1} of {2} - process handle count: {3} - thread handle count: {4}", total_count, ZombiePluralized(total_count), process_name, process_count, thread_count); } } if (!verbose) { Console.WriteLine("Pass -verbose to get full zombie names."); } } catch (Exception ex) { Console.WriteLine(ex.Message); } int[] pids = new int[3]; if (GetConsoleProcessList(pids, 3) == 1) { Console.Write("Press any key to continue"); Console.ReadKey(); } }
private protected override void HandleFile(NtFile file) { var pids = new HashSet <int>(file.GetUsingProcessIds()); WriteObject(NtSystemInfo.GetProcessInformationExtended().Where(p => pids.Contains(p.ProcessId)), true); }