static void Main(string[] args) { bool show_help = false; bool recursive = false; HashSet <string> exclude_dirs = new HashSet <string>(StringComparer.OrdinalIgnoreCase); int pid = Process.GetCurrentProcess().Id; try { OptionSet opts = new OptionSet() { { "r", "Recursive tree directory listing", v => recursive = v != null }, { "sddl", "Print full SDDL security descriptors", v => _print_sddl = v != null }, { "p|pid=", "Specify a PID of a process to impersonate when checking", v => pid = int.Parse(v.Trim()) }, { "w", "Show only write permissions granted", v => _show_write_only = v != null }, { "k=", String.Format("Filter on a specific directory right [{0}]", String.Join(",", Enum.GetNames(typeof(DirectoryAccessRights)))), v => _dir_rights |= ParseRight(v, typeof(DirectoryAccessRights)) }, { "x=", "Specify a base path to exclude from recursive search", v => exclude_dirs.Add(v) }, { "t=", "Specify a type of object to include", v => _type_filter.Add(v) }, { "g", "Map access mask to generic rights.", v => _map_to_generic = v != null }, { "e", "Display errors when opening objects, ignores access denied.", v => _show_errors = v != null }, { "h|help", "show this message and exit", v => show_help = v != null }, }; List <string> paths = opts.Parse(args); if (show_help || (paths.Count == 0)) { ShowHelp(opts); } else { using (NtToken token = NtToken.OpenProcessToken(pid)) { foreach (string path in paths) { try { using (NtDirectory dir = OpenDirectory(path)) { HashSet <string> walked = new HashSet <string>(exclude_dirs, StringComparer.OrdinalIgnoreCase); Console.WriteLine("Dumping Directory: {0}", path); DumpDirectory(dir, token, recursive, walked); } } catch (NtException ex) { Console.WriteLine("Couldn't open {0} - {1}", path, ex.Message); } } } } } catch (Exception e) { Console.WriteLine(e.Message); } }
/// <summary> /// Overidden method to check if an item is a container. /// </summary> /// <param name="path">The drive path to check.</param> /// <returns>True if the item is a container.</returns> protected override bool IsItemContainer(string path) { bool is_container = false; if (GetDrive() == null) { return(false); } path = GetRelativePath(PSPathToNT(path)); // The root always exists. if (path.Length == 0) { return(true); } try { using (NtDirectory dir = GetPathDirectory(path)) { ObjectDirectoryInformation dir_info = GetEntry(dir, path); is_container = dir_info != null && dir_info.TypeName.Equals("directory", StringComparison.OrdinalIgnoreCase); } } catch (NtException) { } return(is_container || GetDrive().DirectoryRoot.DirectoryExists(path)); }
private IEnumerable <string> GetObjectList(string typename) { HashSet <string> walked = new HashSet <string>(StringComparer.OrdinalIgnoreCase); HashSet <string> names = new HashSet <string>(StringComparer.OrdinalIgnoreCase); try { using (NtDirectory dir = NtDirectory.Open(@"\", null, DirectoryAccessRights.Query)) { UpdateObjectList(typename, walked, dir, names); } } catch (NtException) { } try { using (NtDirectory dir = NtDirectory.OpenSessionDirectory("BaseNamedObjects")) { UpdateObjectList(typename, walked, dir, names); } } catch (NtException) { } List <string> ret = new List <string>(names); ret.Sort(); return(ret); }
protected override void GetItem(string path) { if (GetDrive() == null) { return; } string normalized_path = NormalizePath(path); if (_item_cache.ContainsKey(normalized_path)) { ObjectDirectoryEntry entry = _item_cache[normalized_path]; WriteItemObject(entry, path, entry.IsDirectory); } else { using (NtDirectory dir = GetPathDirectory(path)) { ObjectDirectoryInformation dir_info = GetEntry(dir, path); if (dir_info != null) { WriteItemObject(new ObjectDirectoryEntry(GetDrive().DirectoryRoot, normalized_path, dir_info.Name, dir_info.TypeName), path.TrimStart('\\'), dir_info.IsDirectory); } } } }
private void UpdateObjectList(string typename, HashSet <string> walked, NtDirectory dir, HashSet <string> names) { if (!walked.Add(dir.FullPath)) { return; } foreach (var entry in dir.Query()) { if (entry.NtTypeName.Equals(typename, StringComparison.OrdinalIgnoreCase)) { names.Add(entry.FullPath); } else if (entry.IsDirectory) { using (var obj_attr = new ObjectAttributes(entry.Name, AttributeFlags.CaseInsensitive, dir)) { using (var subdir = NtDirectory.Open(obj_attr, DirectoryAccessRights.Query, false)) { if (subdir.IsSuccess) { UpdateObjectList(typename, walked, subdir.Result, names); } } } } } }
private static NtDirectory OpenNamespace(string path) { using (BoundaryDescriptor boundary = BoundaryDescriptor.CreateFromString(path)) { return(NtDirectory.OpenPrivateNamespace(boundary)); } }
private void UpdateObjectList(string typename, HashSet <string> walked, NtDirectory dir, HashSet <string> names) { if (!walked.Add(dir.FullPath)) { return; } foreach (var entry in dir.Query()) { if (entry.NtTypeName.Equals(typename, StringComparison.OrdinalIgnoreCase)) { names.Add(entry.FullPath); } else if (entry.IsDirectory) { try { using (NtDirectory subdir = NtDirectory.Open(entry.Name, dir, DirectoryAccessRights.Query)) { UpdateObjectList(typename, walked, subdir, names); } } catch (NtException) { } } } }
void ISecurityDescriptorCmdletProvider.GetSecurityDescriptor(string path, AccessControlSections includeSections) { string relative_path = GetRelativePath(PSPathToNT(path)); using (NtDirectory dir = GetPathDirectory(relative_path)) { if (relative_path.Length == 0) { WriteItemObject(new GenericObjectSecurity(dir, includeSections), path, true); } else { ObjectDirectoryInformation dir_info = GetEntry(dir, relative_path); if (dir_info == null) { throw new NtException(NtStatus.STATUS_OBJECT_NAME_NOT_FOUND); } using (NtObject obj = dir_info.Open(GenericAccessRights.ReadControl)) { WriteItemObject(new GenericObjectSecurity(obj, includeSections), path, obj is NtDirectory); } } } }
private void GetChildItemsRecursive(string relative_path, bool recurse) { try { using (NtDirectory dir = GetDirectory(relative_path)) { Queue <string> dirs = new Queue <string>(); foreach (ObjectDirectoryInformation dir_info in dir.Query()) { string new_path = BuildRelativePath(relative_path, dir_info.Name); WriteItemObject(new NtDirectoryEntry(GetDrive().DirectoryRoot, new_path, recurse ? new_path : dir_info.Name, dir_info.TypeName), NTPathToPS(BuildDrivePath(new_path)), dir_info.IsDirectory); if (recurse && dir_info.IsDirectory) { dirs.Enqueue(new_path); } } if (recurse && dirs.Count > 0) { foreach (string new_dir in dirs) { GetChildItemsRecursive(new_dir, recurse); } } } } catch (NtException) { if (!recurse) { throw; } } }
static NtDirectory CreateDirectory() { using (var obja = CreateObjectAttributes(null, null)) { return(NtDirectory.Create(obja, DirectoryAccessRights.MaximumAllowed, null)); } }
private static void SetupRootDirectory(NtDirectory root) { ObjectManager.Apply(root, new ObjectManager.ITask[] { new ObjectManager.CloneDirectoryTask("FileSystem"), new ObjectManager.CloneDirectoryTask("Windows"), new ObjectManager.CloneDirectoryTask("Callback"), new ObjectManager.CloneDirectoryTask("Driver"), new ObjectManager.CloneDirectoryTask("DriverStore"), new ObjectManager.CloneDirectoryTask("RPC Control"), new ObjectManager.CloneDirectoryTask("BaseNamedObjects") { new ObjectManager.SymlinkTask("FontCachePort", @"\BaseNamedObjects\FontCachePort", scope: ObjectManager.SymlinkScope.Global), new ObjectManager.SymlinkTask("FontCachePort3.0.0.0", @"\BaseNamedObjects\FontCachePort3.0.0.0", scope: ObjectManager.SymlinkScope.Global), new ObjectManager.SymlinkTask("CoreMessagingRegistrar", @"\BaseNamedObjects\CoreMessagingRegistrar", scope: ObjectManager.SymlinkScope.Global), new ObjectManager.SymlinkTask("Local", @"\BaseNamedObjects"), new ObjectManager.SymlinkTask("Global", @"\BaseNamedObjects"), new ObjectManager.SymlinkTask("Session", @"\Sessions\BNOLINKS"), new ObjectManager.SymlinkTask("AppContainerNamedObject", @"\Sessions\0\AppContainerNamedObject"), new ObjectManager.CloneDirectoryTask("Restricted") }, new ObjectManager.CloneDirectoryTask("GLOBAL??") { new ObjectManager.SymlinkTask("C:", @"\Device\HarddiskVolume4", scope: ObjectManager.SymlinkScope.Global), new ObjectManager.SymlinkTask("D:", @"\Device\HarddiskVolume1", scope: ObjectManager.SymlinkScope.Global), new ObjectManager.SymlinkTask("X:", @"\Device\HarddiskVolume1\vv", scope: ObjectManager.SymlinkScope.Global), new ObjectManager.SymlinkTask("AUX", @"\Device\Null"), new ObjectManager.SymlinkTask("CON", @"\Device\ConDrv\Console"), new ObjectManager.SymlinkTask("CONIN$", @"\Device\ConDrv\CurrentIn"), new ObjectManager.SymlinkTask("CONOUT$", @"\Device\ConDrv\CurrentOut"), new ObjectManager.SymlinkTask("NUL", @"\Device\Null"), new ObjectManager.SymlinkTask("PIPE", @"\Device\NamedPipe"), new ObjectManager.SymlinkTask("Tcp", @"\Device\Tcp"), }, }); }
/// <summary> /// Finds ALPC endpoints which allows for the server binding. This brute forces all ALPC ports to try and find /// something which will accept the bind. /// </summary> /// <remarks>This could hang if the ALPC port is owned by a suspended process.</remarks> /// <param name="interface_id">Interface UUID to lookup.</param> /// <param name="interface_version">Interface version lookup.</param> /// <returns>A list of RPC endpoints which can bind the interface.</returns> /// <exception cref="NtException">Throws on error.</exception> public static IEnumerable <RpcEndpoint> FindAlpcEndpointForInterface(Guid interface_id, Version interface_version) { using (var dir = NtDirectory.Open(@"\RPC Control")) { var nt_type = NtType.GetTypeByType <NtAlpc>().Name; foreach (var port in dir.Query().Where(e => e.NtTypeName == nt_type)) { bool success = false; try { using (var server = new RpcClient(interface_id, interface_version)) { server.Connect(port.Name); success = true; } } catch { } if (success) { yield return(new RpcEndpoint(interface_id, interface_version, SafeRpcBindingHandle.Compose(null, "ncalrpc", null, port.Name, null), false)); } } } }
public override NtObject NewItem(string relative_path, string item_type_name, object new_item_value) { switch (item_type_name.ToLower()) { case "event": return(NtEvent.Create(relative_path, _dir, EventType.NotificationEvent, false)); case "directory": return(NtDirectory.Create(relative_path, _dir, DirectoryAccessRights.MaximumAllowed)); case "symboliclink": case "link": if (new_item_value == null) { throw new ArgumentNullException(nameof(new_item_value), "Must specify value for the symbolic link"); } return(NtSymbolicLink.Create(relative_path, _dir, new_item_value.ToString())); case "mutant": return(NtMutant.Create(relative_path, _dir, false)); case "semaphore": int max_count = 1; if (new_item_value != null) { max_count = Convert.ToInt32(new_item_value); } return(NtSemaphore.Create(relative_path, _dir, 0, max_count)); default: throw new ArgumentException($"Can't create new object of type {item_type_name}"); } }
private void FindDevicesInDirectory(NtDirectory dir, Dictionary <string, SecurityDescriptorEntry> devices, int current_depth) { if (Stopping || current_depth <= 0) { return; } foreach (var entry in dir.Query()) { if (entry.IsDirectory && Recurse) { using (var new_dir = OpenDirectory(entry.Name, dir)) { if (new_dir.IsSuccess) { FindDevicesInDirectory(new_dir.Result, devices, current_depth - 1); } else { WriteAccessWarning(dir, entry.Name, new_dir.Status); } } } else { if (entry.NtTypeName.Equals("Device", StringComparison.OrdinalIgnoreCase)) { if (!devices.ContainsKey(entry.FullPath)) { devices.Add(entry.FullPath, GetSecurityDescriptor(entry.FullPath)); } } } } }
/// <summary> /// Overriden method to check if an item exists. /// </summary> /// <param name="path">The drive path to check.</param> /// <returns>True if the item exists.</returns> protected override bool ItemExists(string path) { bool exists = false; if (GetDrive() == null) { return(false); } path = GetRelativePath(PSPathToNT(path)); if (path.Length == 0) { return(true); } try { using (NtDirectory dir = GetPathDirectory(path)) { exists = GetEntry(dir, path) != null; } } catch (NtException) { } // If we can't find it indirectly, at least see if there's a directory with this name. return(exists || GetDrive().DirectoryRoot.DirectoryExists(path)); }
/// <summary> /// Overridden method to get the item from a path. /// </summary> /// <param name="path">The drive path.</param> protected override void GetItem(string path) { if (GetDrive() == null) { return; } string relative_path = GetRelativePath(PSPathToNT(path)); using (NtDirectory dir = GetPathDirectory(relative_path)) { if (relative_path.Length == 0) { WriteItemObject(new NtDirectoryEntry(GetDrive().DirectoryRoot, relative_path, String.Empty, "Directory"), NTPathToPS(BuildDrivePath(relative_path)), true); } else { ObjectDirectoryInformation dir_info = GetEntry(dir, relative_path); if (dir_info != null) { WriteItemObject(new NtDirectoryEntry(GetDrive().DirectoryRoot, relative_path, dir_info.Name, dir_info.TypeName), NTPathToPS(BuildDrivePath(relative_path)), dir_info.IsDirectory); } } } }
IEnumerable <string> ExpandDirectoryEntryMatches(string path) { Queue <string> remaining = new Queue <string>(path.Split('\\')); List <string> matches = new List <string>(); if (remaining.Count == 0) { return(matches); } try { string base_path = String.Join(@"\", remaining.Take(remaining.Count - 1)); NtDirectory root_dir = GetDrive().DirectoryRoot; // We'll first try the general case of unglobbed dir and a globbed final name. using (NtDirectory base_dir = remaining.Count > 1 ? NtDirectory.Open(base_path, root_dir, DirectoryAccessRights.Query) : root_dir.Duplicate(DirectoryAccessRights.Query)) { AddMatches(base_dir, BuildRelativePath(base_path, String.Empty), new string[] { remaining.Last() }, matches); } } catch (NtException) { // If we couldn't open the drive then try brute force approach. AddMatches(GetDrive().DirectoryRoot, String.Empty, remaining, matches); } return(matches.Select(s => NTPathToPS(BuildDrivePath(s)))); }
/// <summary> /// Overridden method to create a new drive. /// </summary> /// <param name="drive">The template drive info.</param> /// <returns>The new drive info.</returns> protected override PSDriveInfo NewDrive(PSDriveInfo drive) { if (drive == null) { WriteError(new ErrorRecord( new ArgumentNullException(nameof(drive)), "NullDrive", ErrorCategory.InvalidArgument, null)); return(null); } if (string.IsNullOrWhiteSpace(drive.Root) && (!drive.Root.StartsWith(GLOBAL_ROOT) || !drive.Root.StartsWith(NAMESPACE_ROOT))) { WriteError(new ErrorRecord( new ArgumentNullException("drive.Root"), "InvalidRoot", ErrorCategory.InvalidArgument, null)); return(null); } try { if (drive.Root.StartsWith(NAMESPACE_ROOT)) { using (var descriptor = BoundaryDescriptor.CreateFromString(drive.Root.Substring(NAMESPACE_ROOT.Length))) { using (NtDirectory dir = NtDirectory.OpenPrivateNamespace(descriptor)) { ObjectManagerPSDriveInfo objmgr_drive = new ObjectManagerPSDriveInfo(dir.Duplicate(), drive); return(objmgr_drive); } } } else { using (NtDirectory root = NtDirectory.Open(@"\")) { using (NtDirectory dir = NtDirectory.Open(drive.Root.Substring(GLOBAL_ROOT.Length), root, DirectoryAccessRights.MaximumAllowed)) { ObjectManagerPSDriveInfo objmgr_drive = new ObjectManagerPSDriveInfo(dir.Duplicate(), drive); return(objmgr_drive); } } } } catch (NtException ex) { WriteError(new ErrorRecord( ex, "NoRoot", ErrorCategory.PermissionDenied, drive)); return(null); } }
private static NtResult <NtDirectory> OpenDirectory(string path, NtObject root) { using (ObjectAttributes obja = new ObjectAttributes(path, AttributeFlags.CaseInsensitive, root)) { return(NtDirectory.Open(obja, DirectoryAccessRights.Query, false)); } }
private void DumpDirectory(IEnumerable <TokenEntry> tokens, HashSet <string> type_filter, AccessMask access_rights, NtDirectory dir, int current_depth) { DumpObject(tokens, type_filter, access_rights, dir, true); if (Stopping || current_depth <= 0) { return; } if (Recurse && dir.IsAccessGranted(DirectoryAccessRights.Query)) { foreach (var entry in dir.Query()) { if (entry.IsDirectory) { using (var new_dir = OpenDirectory(entry.Name, dir)) { if (new_dir.IsSuccess) { DumpDirectory(tokens, type_filter, access_rights, new_dir.Result, current_depth - 1); } else { WriteAccessWarning(dir, entry.Name, new_dir.Status); } } } else { NtType type = entry.NtType; if (IsTypeFiltered(type.Name, type_filter) && !type.Name.Equals("Device", StringComparison.OrdinalIgnoreCase) && !type.Name.Equals("Key", StringComparison.OrdinalIgnoreCase)) { if (type.CanOpen) { using (var result = OpenObject(entry, dir, GenericAccessRights.MaximumAllowed)) { if (result.IsSuccess) { DumpObject(tokens, type_filter, access_rights, result.Result, false); } else { WriteAccessWarning(dir, entry.Name, result.Status); } } } else { WriteWarning(String.Format(@"Can't open {0}\{1} with type {2}", dir.FullPath, entry.Name, entry.NtTypeName)); } } } } } }
public NtDirectoryContainer(NtDirectory dir) : base(dir) { _dir = dir; if (dir.FullPath == @"\") { _key = new NtKeyContainer(); } }
/// <summary> /// Get the Win32 path for a specified path. /// </summary> /// <param name="path">The path component.</param> /// <returns>The full NT path.</returns> protected virtual string GetWin32Path(string path) { if (path.StartsWith(@"\")) { throw new ArgumentException("Win32 paths can't start with a path separator"); } return($@"{NtDirectory.GetBasedNamedObjects()}\{path}"); }
public override NtResult <NtObjectContainer> OpenForQuery(string relative_path, bool throw_on_error) { if (IsRegistryPath(relative_path)) { return(_key.OpenForQuery(GetRegistryPath(relative_path), throw_on_error)); } return(NtDirectory.Open(relative_path, _dir, DirectoryAccessRights.Query, throw_on_error).Map(Create)); }
static void UpdateDacl(string typename, NtDirectory root, string name, SecurityDescriptor sd) { using (var obj = NtObject.OpenWithType(typename, name, root, AttributeFlags.CaseInsensitive, GenericAccessRights.WriteDac, null, false)) { if (obj.IsSuccess) { obj.Result.SetSecurityDescriptor(sd, SecurityInformation.Dacl); } } }
private ObjectDirectoryInformation GetEntry(NtDirectory dir, string path) { int last_slash = path.LastIndexOf('\\'); if (last_slash != -1) { path = path.Substring(last_slash + 1); } return(dir.GetDirectoryEntry(path)); }
static void FixupDbgView() { var sd = CreateSecurityDescriptor(); using (NtDirectory objdir = NtDirectory.OpenBaseNamedObjects()) { UpdateDacl("event", objdir, "DBWIN_DATA_READY", sd); UpdateDacl("section", objdir, "DBWIN_BUFFER", sd); UpdateDacl("event", objdir, "DBWIN_BUFFER_READY", sd); } }
private static NtDirectory OpenPath(ObjectDirectory root, string path) { try { return(NtDirectory.Open(path, root != null ? root._directory : null, DirectoryAccessRights.MaximumAllowed)); } catch (NtException ex) { throw ex.AsWin32Exception(); } }
public NtDirectory OpenDirectory() { if (Name.StartsWith(@"\") || Directory != null) { return(NtDirectory.Open(Name, Directory, DirectoryAccessRights.MaximumAllowed)); } else { return(NtDirectory.OpenPrivateNamespace(BoundaryDescriptor.CreateFromString(Name))); } }
static NtDirectory OpenDirectory(string name) { if (name.StartsWith(@"\")) { return(NtDirectory.Open(name)); } else { return(NtDirectory.OpenPrivateNamespace(BoundaryDescriptor.CreateFromString(name))); } }
private bool disposedValue = false; // To detect redundant calls private void Dispose(bool disposing) { if (!disposedValue) { if (_directory != null) { _directory.Close(); _directory = null; } disposedValue = true; } }
internal ObjectDirectory(ObjectDirectory root, string object_path) { _orig_path = object_path; if (_orig_path.StartsWith("\\") || root != null) { _directory = OpenPath(root, _orig_path); } else { _directory = OpenNamespace(_orig_path); } PopulateEntries(); }
internal NtDirectoryEntry(NtDirectory base_directory, string relative_path, string name, string typename) { Name = name; TypeName = typename; RelativePath = relative_path; _base_directory = base_directory; switch (typename.ToLower()) { case "directory": case "key": IsDirectory = true; break; case "symboliclink": IsSymbolicLink = true; break; } _maximum_granted_access = 0; }
private ObjectDirectoryInformation GetEntry(NtDirectory dir, string path) { int last_slash = path.LastIndexOf('\\'); if (last_slash != -1) { path = path.Substring(last_slash + 1); } return dir.GetDirectoryEntry(path); }
public ObjectManagerPSDriveInfo(NtDirectory root, PSDriveInfo drive_info) : base(drive_info) { DirectoryRoot = root; }
private void AddMatches(NtDirectory root, string base_path, IEnumerable<string> remaining, List<string> matches) { string current_entry = remaining.First(); bool is_leaf = remaining.Count() == 1; List<ObjectDirectoryInformation> matching_entries = new List<ObjectDirectoryInformation>(); if (root.IsAccessGranted(DirectoryAccessRights.Query)) { // If this is not a leaf point we don't care about non-directory entries. ObjectDirectoryInformation[] dir_infos = root.Query().Where(d => is_leaf || d.IsDirectory).ToArray(); foreach (ObjectDirectoryInformation dir_info in dir_infos) { if (dir_info.Name.Equals(current_entry, StringComparison.OrdinalIgnoreCase)) { matching_entries.Add(dir_info); break; } } // If we didn't find an explicit match then see if it's a glob. if (matching_entries.Count == 0 && HasGlobChars(current_entry)) { Regex globber = GlobToRegex(current_entry, false); foreach (ObjectDirectoryInformation dir_info in dir_infos) { if (globber.IsMatch(dir_info.Name)) { matching_entries.Add(dir_info); } } } } // Nothing matched. if (matching_entries.Count == 0) { return; } // We've reached the end of the road. if (is_leaf) { foreach (ObjectDirectoryInformation dir_info in matching_entries) { string full_path = base_path + dir_info.Name; _item_cache[full_path] = new NtDirectoryEntry(GetDrive().DirectoryRoot, PSPathToNT(full_path), dir_info.Name, dir_info.TypeName); matches.Add(full_path); } } else { foreach (ObjectDirectoryInformation entry in matching_entries) { try { using (NtDirectory dir = NtDirectory.Open(entry.Name, root, DirectoryAccessRights.Query)) { AddMatches(dir, base_path + entry.Name + @"\", remaining.Skip(1), matches); } } catch (NtException) { } } } }