private static void Iterate(int indent, NtObjectBase item) { void Write(string str) { for (int i = 0; i < indent; i++) { Console.Write(' '); } Console.WriteLine(str); } Write($"{item.Type}: {item.FullName}"); if (item is PhysicalDriveIdentifier physicalDriveIdentifier) { Write($" PhysicalDrive{physicalDriveIdentifier.Identifier} {physicalDriveIdentifier.FileAddress}"); } if (item is HarddiskVolumeIdentifier volumeIdentifier) { Write($" Volume{volumeIdentifier.Identifier} {volumeIdentifier.FileAddress}"); } if (item is HarddiskPartitionIdentifier partitionIdentifier) { Write($" Partition{partitionIdentifier.Partition}, PhysicalDrive{partitionIdentifier.Harddisk} {partitionIdentifier.FileAddress}"); } if (item.IsSymbolicLink) { if (item.TryGetSymbolicLinkTarget(out string target)) { Write($" => {target}"); } else { Write(" => UNABLE TO LOCATE"); } } if (item is NtDirectory asDir) { try { foreach (NtObjectBase @base in asDir.ListDirectory()) { Iterate(indent + 2, @base); } } catch (NtObjectException e) { Write(" UNABLE TO ENUMERATE DIRECTORY, " + e.StatusCode); } Console.WriteLine(); } }
internal NtObjectBase ConvertToSpecificType(NtObjectBase @object) { if (@object is NtDirectory) { return(@object); } Match match; if (@object.Type == WellKnownType.SymbolicLink) { if ((match = PhysicalDriveRegex.Match(@object.Name)).Success) { int id = int.Parse(match.Groups[1].Value); return(new PhysicalDriveIdentifier(@object.TypeName, @object.Parent, @object.Name, id)); } if ((match = PartitionRegex.Match(@object.Name)).Success) { int partitionIdx = int.Parse(match.Groups[1].Value); match = HarddiskRegex.Match(@object.Parent); if (match.Success) { int harddiskIdx = int.Parse(match.Groups[1].Value); return(new HarddiskPartitionIdentifier(@object.TypeName, @object.Parent, @object.Name, harddiskIdx, partitionIdx)); } } if ((match = HarddiskPartitionRegex.Match(@object.Name)).Success) { int harddiskIdx = int.Parse(match.Groups[1].Value); int partitionIdx = int.Parse(match.Groups[2].Value); return(new HarddiskPartitionIdentifier(@object.TypeName, @object.Parent, @object.Name, harddiskIdx, partitionIdx)); } if ((match = DriveLetterRegex.Match(@object.Name)).Success) { string letter = match.Groups[1].Value; return(new DriveLetterIdentifier(@object.TypeName, @object.Parent, @object.Name, letter)); } } if (@object.Type == WellKnownType.Device && (match = HarddiskVolumeRegex.Match(@object.Name)).Success) { int id = int.Parse(match.Groups[1].Value); return(new HarddiskVolumeIdentifier(@object.TypeName, @object.Parent, @object.Name, id)); } return(@object); }
public bool TryGetVolume(out HarddiskVolumeIdentifier volumeIdentifier) { volumeIdentifier = null; if (!TryGetSymbolicLinkTarget(out string target)) { return(false); } NtObjectBase obj = NtObjects.Instance.GetSingleObject(target); volumeIdentifier = obj as HarddiskVolumeIdentifier; return(volumeIdentifier != null); }
public IEnumerable <NtObjectBase> ListDirectory(string path, bool recurse = false, WellKnownType filterType = WellKnownType.Unknown) { OBJECT_ATTRIBUTES objectAttributes = new OBJECT_ATTRIBUTES(path, 0); NtStatus retVal = Win32.NtOpenDirectoryObject(out var directoryHandle, DirectoryAccessEnum.DIRECTORY_QUERY, ref objectAttributes); if (retVal != NtStatus.STATUS_SUCCESS) { ErrorHelper.Throw(retVal, $"NtOpenDirectoryObject, parentPath: {path}"); } uint singleDirInfo = (uint)Marshal.SizeOf <OBJECT_DIRECTORY_INFORMATION>(); using (directoryHandle) using (UnmanagedMemory mem = new UnmanagedMemory((int)(256 * singleDirInfo))) { bool restart = true; NtStatus status; uint context = 0; do { mem.Clear(); status = Win32.NtQueryDirectoryObject(directoryHandle, mem.Handle, mem.Bytes, false, restart, ref context, out _); restart = false; IntPtr ptr = mem.Handle; while (true) { OBJECT_DIRECTORY_INFORMATION dir = Marshal.PtrToStructure <OBJECT_DIRECTORY_INFORMATION>(ptr); ptr = new IntPtr(ptr.ToInt64() + (int)singleDirInfo); if (dir.Name.Length == 0) { break; } string typeName = dir.TypeName.ToString(); string name = dir.Name.ToString(); WellKnownType wellKnownType = StaticStrings.ToWellKnownType(typeName); if (filterType != WellKnownType.Unknown && filterType != wellKnownType) { continue; } if (wellKnownType == WellKnownType.Directory) { NtDirectory directory = new NtDirectory(typeName, path, name); yield return(directory); if (recurse) { foreach (NtObjectBase subObject in ListDirectory(directory.FullName, true, filterType)) { yield return(subObject); } } continue; } NtObjectBase result = new NtObjectBase(typeName, path, name); result = ConvertToSpecificType(result); yield return(result); } } while (status == NtStatus.STATUS_MORE_ENTRIES); } }
public static void Main(string[] args) { //var pp = NtObjects.Instance.GetSingleObject(@"\Device\Csc"); //var pp1 = pp.GetSymbolicLinkObject(); var objects = ListAll() //.Where(s => s.FullName.StartsWith(@"\Device")) .OrderBy(s => s.FullName) .Select(s => { Dictionary <string, object> item = new Dictionary <string, object>(); foreach (PropertyInfo property in s.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (!property.CanRead) { continue; } object value = property.GetValue(s); if (value is bool bl && !bl) { continue; } item[property.Name] = value; } if (s is NtDirectory dir) { try { item["Children"] = dir.ListDirectory().Select(x => x.FullName).ToArray(); } catch (Exception) { } } if (s.GetType() != typeof(NtObjectBase)) { item["Interpreted"] = s.GetType().Name; } if (s.IsSymbolicLink) { List <Dictionary <string, object> > symlinks = new List <Dictionary <string, object> >(); item["IsSymbolicLink"] = true; item["SymbolicLinkChain"] = symlinks; NtObjectBase linkItem = s; while (linkItem.IsSymbolicLink && linkItem.TryGetSymbolicLinkObject(out NtObjectBase target)) { symlinks.Add(new Dictionary <string, object> { { "SymlinkTarget", target.FullName }, { "SymlinkTargetType", target.Type } }); linkItem = target; } } return(item); }); string json = JsonConvert.SerializeObject(objects, Formatting.Indented, new StringEnumConverter()); Console.WriteLine(json); }