private static EaBuffer CreateDummyEaBuffer()
        {
            EaBuffer ea = new EaBuffer();

            ea.AddEntry("GARBAGE", new byte[16], EaBufferEntryFlags.NeedEa);
            return(ea);
        }
        static CheckResult CheckDevice(string name, bool writable, EaBuffer ea_buffer)
        {
            CheckResult result = new CheckResult(name, NtStatus.STATUS_INVALID_PARAMETER, FileDeviceType.UNKNOWN);

            try
            {
                using (var imp = NtToken.Impersonate(_pid,
                                                     _identify_only ? SecurityImpersonationLevel.Identification : SecurityImpersonationLevel.Impersonation))
                {
                    FileAccessRights access_mask = FileAccessRights.GenericRead;
                    if (writable)
                    {
                        access_mask |= FileAccessRights.GenericWrite;
                    }

                    FileOpenOptions opts = _open_as_dir ? FileOpenOptions.DirectoryFile : FileOpenOptions.NonDirectoryFile;
                    using (NtFile file = NtFile.Create(name, null, access_mask, NtApiDotNet.FileAttributes.Normal,
                                                       FileShareMode.All, opts, FileDisposition.Open, ea_buffer))
                    {
                        result = new CheckResult(name, NtStatus.STATUS_SUCCESS, file.DeviceType);
                    }
                }
            }
            catch (NtException ex)
            {
                result = new CheckResult(name, ex.Status, FileDeviceType.UNKNOWN);
            }

            return(result);
        }
Beispiel #3
0
        private protected override void RunAccessCheck(IEnumerable <TokenEntry> tokens)
        {
            HashSet <string> devices = new HashSet <string>(StringComparer.OrdinalIgnoreCase);

            foreach (string path in Path)
            {
                using (var result = OpenDirectory(path, null))
                {
                    if (result.IsSuccess)
                    {
                        FindDevicesInDirectory(result.Result, devices, MaxDepth ?? int.MaxValue);
                    }
                    else
                    {
                        // If failed, it might be an absolute path so just add it.
                        devices.Add(path);
                    }
                }
            }

            if (devices.Count > 0)
            {
                AccessMask    access_rights   = _file_type.MapGenericRights(AccessRights);
                EaBuffer      ea_buffer       = CheckEaBuffer ? (EaBuffer ?? CreateDummyEaBuffer()) : null;
                List <string> namespace_paths = new List <string>(NamespacePath ?? new[] { "XYZ" });

                foreach (var entry in tokens)
                {
                    foreach (string path in devices)
                    {
                        if (CheckDevice())
                        {
                            CheckAccessUnderImpersonation(entry, path, false, access_rights, OpenOptions, ea_buffer);
                        }

                        if (CheckNamespace())
                        {
                            foreach (string namespace_path in namespace_paths)
                            {
                                CheckAccessUnderImpersonation(entry, path + @"\" + namespace_path,
                                                              true, access_rights, OpenOptions, ea_buffer);
                            }
                        }
                    }
                }
            }
            else
            {
                WriteWarning("Couldn't find any devices to check");
            }
        }
Beispiel #4
0
 static NtSection RemapFileAsRW()
 {
     string base_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "luafv_" + Guid.NewGuid());
     Console.WriteLine("Base Path: {0}", base_path);
     DirectorySecurity dir_sd = new DirectorySecurity();
     Directory.CreateDirectory(base_path);
     string target_path = NtFileUtils.DosFileNameToNt(Path.Combine(base_path, "dummy.txt"));
     string license_file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "license.rtf");
     Console.WriteLine("Trying to map {0} R/W", license_file);
     NtFile.CreateHardlink(NtFileUtils.DosFileNameToNt(license_file), target_path);
     using (var oplock_file = NtFile.Open(target_path, null, FileAccessRights.ReadAttributes, FileShareMode.All, FileOpenOptions.NonDirectoryFile))
     {
         var oplock = oplock_file.RequestOplockAsync(OplockLevelCache.Read | OplockLevelCache.Write, RequestOplockInputFlag.Request);
         Console.WriteLine("Started oplock");
         SetVirtualization(true);
         Console.WriteLine("Opening file");
         using (var file = NtFile.Open(target_path, null, FileAccessRights.GenericRead
             | FileAccessRights.GenericWrite, FileShareMode.All,
             FileOpenOptions.NonDirectoryFile | FileOpenOptions.CompleteIfOplocked))
         {
             SetVirtualization(false);
             Console.WriteLine("{0} {1}", NtProcess.Current.ProcessId, file.Handle.DangerousGetHandle());
             Console.WriteLine("{0} {1}", file.FullPath, file.GrantedAccess);
             CreateVirtualStoreFile(target_path, GetDummyBuffer());
             
             var async_read = file.ReadAsync(1, 0);
             if (!oplock.Wait(10000))
             {
                 throw new Exception("Oplock Timed Out");
             }
             Console.WriteLine("Oplock Fired");
             EaBuffer ea = new EaBuffer();
             ea.AddEntry("Hello", new byte[16], EaBufferEntryFlags.None);
             // Set EA to force the delayed virtualization to complete without triggering oplock.
             Console.WriteLine("Setting EA");
             file.SetEa(ea);
             Console.WriteLine("File now {0}", file.FullPath);
             oplock_file.Close();
             Console.WriteLine("Closed oplock_file");
             if (!async_read.Wait(10000))
             {
                 throw new Exception("Async Read Timed Out");
             }
             Console.WriteLine("Read Complete");
             return NtSection.Create(null, SectionAccessRights.MaximumAllowed, null,
                 MemoryAllocationProtect.ReadWrite, SectionAttributes.Commit, file);
         }
     }
 }
        private protected override void RunAccessCheck(IEnumerable <TokenEntry> tokens)
        {
            var devices = new Dictionary <string, SecurityDescriptorEntry>(StringComparer.OrdinalIgnoreCase);

            foreach (string path in Path)
            {
                using (var result = OpenDirectory(path, null))
                {
                    if (result.IsSuccess)
                    {
                        FindDevicesInDirectory(result.Result, devices, MaxDepth ?? int.MaxValue);
                    }
                    else
                    {
                        // If failed, it might be an absolute path so just add it.
                        if (!devices.ContainsKey(path))
                        {
                            devices.Add(path, GetSecurityDescriptor(path));
                        }
                    }
                }
            }

            if (devices.Count > 0)
            {
                AccessMask    access_rights   = _file_type.MapGenericRights(Access);
                EaBuffer      ea_buffer       = CheckEaBuffer ? (EaBuffer ?? CreateDummyEaBuffer()) : null;
                List <string> namespace_paths = new List <string>(NamespacePath ?? new[] { "XYZ" });

                foreach (var entry in tokens)
                {
                    foreach (var pair in devices)
                    {
                        if (CheckDevice())
                        {
                            if (pair.Value != null)
                            {
                                AccessMask granted_access = NtSecurity.GetMaximumAccess(pair.Value.SecurityDescriptor, entry.Token, _file_type.GenericMapping);
                                if (IsAccessGranted(granted_access, access_rights))
                                {
                                    WriteObject(new DeviceAccessCheckResult(pair.Key, false, pair.Value.DeviceType,
                                                                            pair.Value.Characteristics, granted_access,
                                                                            pair.Value.SecurityDescriptor, entry.Information));
                                }
                            }
                            else
                            {
                                if (!NoImpersonation)
                                {
                                    CheckAccessUnderImpersonation(entry, pair.Key, false, access_rights, OpenOptions, ea_buffer);
                                }
                            }
                        }

                        if (CheckNamespace() && !NoImpersonation)
                        {
                            foreach (string namespace_path in namespace_paths)
                            {
                                CheckAccessUnderImpersonation(entry, pair.Key + @"\" + namespace_path,
                                                              true, access_rights, OpenOptions, ea_buffer);
                            }
                        }
                    }
                }
            }
            else
            {
                WriteWarning("Couldn't find any devices to check");
            }
        }
        private void CheckAccessUnderImpersonation(TokenEntry token, string path, bool namespace_path,
                                                   AccessMask access_rights, FileOpenOptions open_options, EaBuffer ea_buffer)
        {
            using (var result = OpenUnderImpersonation(token, path, open_options, ea_buffer))
            {
                if (result.IsSuccess)
                {
                    if (IsAccessGranted(result.Result.GrantedAccessMask, access_rights))
                    {
                        var sd = result.Result.GetSecurityDescriptor(SecurityInformation.AllBasic, false);

                        WriteObject(new DeviceAccessCheckResult(path, namespace_path, GetDeviceType(result.Result),
                                                                GetDeviceCharacteristics(result.Result), result.Result.GrantedAccess,
                                                                sd.IsSuccess ? sd.Result : null, token.Information));
                    }
                }
                else
                {
                    WriteWarning($"Opening {path} failed: {result.Status}");
                }
            }
        }
 private static NtResult <NtFile> OpenUnderImpersonation(TokenEntry token, string path, FileOpenOptions open_options, EaBuffer ea_buffer)
 {
     using (var obja = new ObjectAttributes(path, AttributeFlags.CaseInsensitive))
     {
         return(token.Token.RunUnderImpersonate(() => NtFile.Create(obja, FileAccessRights.MaximumAllowed,
                                                                    FileAttributes.None, FileShareMode.None, open_options, FileDisposition.Open, ea_buffer, false)));
     }
 }
        static void Main(string[] args)
        {
            bool   show_help      = false;
            bool   map_to_symlink = false;
            bool   readable       = false;
            bool   ea_buffer      = false;
            string suffix         = "XYZ";
            string namelist       = null;

            _pid = Process.GetCurrentProcess().Id;

            try
            {
                OptionSet opts = new OptionSet()
                {
                    { "r", "Recursive tree directory listing",
                      v => _recursive = v != null },
                    { "l", "Try and map device names to a symlink", v => map_to_symlink = v != null },
                    { "p|pid=", "Specify a PID of a process to impersonate when checking", v => _pid = int.Parse(v.Trim()) },
                    { "suffix=", "Specify the suffix for the namespace search", v => suffix = v },
                    { "namelist=", "Specify a text file with a list of names", v => namelist = v },
                    { "ea", "Try and show only devices with accept an EA buffer", v => ea_buffer = v != null },
                    { "e", "Display errors when trying devices, ignores Access Denied", v => _show_errors = v != null },
                    { "i", "Use an identify level token when impersonating", v => _identify_only = v != null },
                    { "d", "Try opening devices as directories rather than files", v => _open_as_dir = v != null },
                    { "f", "Filter out devices which could be opened direct and via namespace", v => _filter_direct = v != null },
                    { "readonly", "Show devices which can be opened for read access instead of write", v => readable = v != null },
                    { "h|help", "show this message and exit",
                      v => show_help = v != null },
                };

                List <string> names = opts.Parse(args);

                if (namelist != null)
                {
                    names.AddRange(File.ReadAllLines(namelist));
                }

                if (names.Count == 0 || show_help)
                {
                    ShowHelp(opts);
                }
                else
                {
                    List <string> device_objs;

                    if (_recursive)
                    {
                        device_objs = FindDeviceObjects(names);
                    }
                    else
                    {
                        device_objs = names;
                    }

                    if (device_objs.Count > 0)
                    {
                        EaBuffer ea = null;
                        if (ea_buffer)
                        {
                            ea = new EaBuffer();
                            ea.AddEntry("GARBAGE", new byte[16], EaBufferEntryFlags.NeedEa);
                        }

                        IEnumerable <CheckResult>   write_normal    = device_objs.Select(n => CheckDevice(n, !readable, ea));
                        IEnumerable <CheckResult>   write_namespace = device_objs.Select(n => CheckDevice(n + "\\" + suffix, !readable, ea));
                        Dictionary <string, string> symlinks        = FindSymlinks();

                        if (ea_buffer)
                        {
                            _show_errors    = true;
                            write_normal    = write_normal.Where(e => e.Status == NtStatus.STATUS_INVALID_PARAMETER);
                            write_namespace = write_namespace.Where(e => e.Status == NtStatus.STATUS_INVALID_PARAMETER);
                        }

                        if (_filter_direct)
                        {
                            Console.WriteLine("Namespace Only");
                            HashSet <string> normal = new HashSet <string>(write_normal.Where(r => r.Status.IsSuccess()).Select(r => r.Path), StringComparer.OrdinalIgnoreCase);
                            DumpList(write_namespace.Where(r => !normal.Contains(r.Path)), map_to_symlink, symlinks);
                        }
                        else
                        {
                            Console.WriteLine("{0} Access", readable ? "Read" : "Write");
                            DumpList(write_normal, map_to_symlink, symlinks);
                            Console.WriteLine();
                            Console.WriteLine("{0} Access with Namespace", readable ? "Read" : "Write");
                            DumpList(write_namespace, map_to_symlink, symlinks);
                        }
                    }
                    else
                    {
                        Console.WriteLine("No device names specified");
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
 private void CheckAccessUnderImpersonation(TokenEntry token, string path, AccessMask access_rights, FileOpenOptions open_options, EaBuffer ea_buffer)
 {
     using (var result = OpenUnderImpersonation(token, path, open_options, ea_buffer))
     {
         if (result.IsSuccess)
         {
             if (IsAccessGranted(result.Result.GrantedAccessMask, access_rights))
             {
                 WriteAccessCheckResult(path, "Device", result.Result.GrantedAccess, _file_type.GenericMapping,
                                        String.Empty, _file_type.AccessRightsType, token.Information);
             }
         }
         else
         {
             WriteWarning(String.Format("Opening {0} failed: {1}", path, result.Status));
         }
     }
 }