/// <summary>
        /// Enumerates rights explicitly given to the specified SID. If the given SID
        /// doesn't have any directly applied rights, returns an empty collection.
        /// </summary>
        public static IEnumerable <string> LsaEnumerateAccountRights(LsaHandle policyHandle, ref SID sid)
        {
            NTSTATUS status = Imports.LsaEnumerateAccountRights(policyHandle, ref sid, out var rightsBuffer, out uint rightsCount);

            switch (status)
            {
            case NTSTATUS.STATUS_OBJECT_NAME_NOT_FOUND:
                return(Enumerable.Empty <string>());

            case NTSTATUS.STATUS_SUCCESS:
                break;

            default:
                throw ErrorMethods.GetIoExceptionForNTStatus(status);
            }

            List <string> rights = new List <string>();
            Reader        reader = new Reader(rightsBuffer);

            for (int i = 0; i < rightsCount; i++)
            {
                rights.Add(reader.ReadUNICODE_STRING());
            }

            return(rights);
        }
Exemple #2
0
        /// <summary>
        /// Get the ids for all processes that have a handle to this file system object.
        /// Does not include the current process.
        /// </summary>
        public unsafe static IEnumerable <UIntPtr> GetProcessIds(SafeFileHandle fileHandle)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                NTSTATUS status = NTSTATUS.STATUS_INFO_LENGTH_MISMATCH;

                while (status == NTSTATUS.STATUS_INFO_LENGTH_MISMATCH)
                {
                    status = Imports.NtQueryInformationFile(fileHandle, out IO_STATUS_BLOCK statusBlock,
                                                            buffer.VoidPointer, (uint)buffer.ByteCapacity, FileInformationClass.FileProcessIdsUsingFileInformation);

                    switch (status)
                    {
                    case NTSTATUS.STATUS_SUCCESS:
                        break;

                    case NTSTATUS.STATUS_INFO_LENGTH_MISMATCH:
                        // Not a big enough buffer
                        buffer.EnsureByteCapacity((ulong)statusBlock.Information);
                        break;

                    default:
                        throw ErrorMethods.GetIoExceptionForNTStatus(status);
                    }
                }

                return ((FILE_PROCESS_IDS_USING_FILE_INFORMATION *)buffer.VoidPointer)->ProcessIdList.ToArray();
            }));
        }
Exemple #3
0
            private void GetData()
            {
                NTSTATUS status = FileMethods.Imports.NtQueryDirectoryFile(
                    FileHandle: _directory,
                    Event: IntPtr.Zero,
                    ApcRoutine: null,
                    ApcContext: IntPtr.Zero,
                    IoStatusBlock: out IO_STATUS_BLOCK statusBlock,
                    FileInformation: _buffer.VoidPointer,
                    Length: (uint)_buffer.ByteCapacity,
                    FileInformationClass: FileInformationClass.FileFullDirectoryInformation,
                    ReturnSingleEntry: false,
                    FileName: null,
                    RestartScan: false);

                switch (status)
                {
                case NTSTATUS.STATUS_NO_MORE_FILES:
                    NoMoreFiles();
                    return;

                case NTSTATUS.STATUS_SUCCESS:
                    Debug.Assert(statusBlock.Information.ToInt64() != 0);
                    break;

                default:
                    throw ErrorMethods.GetIoExceptionForNTStatus(status);
                }
            }
        public static void LsaFreeMemory(IntPtr handle)
        {
            NTSTATUS status = Imports.LsaFreeMemory(handle);

            if (status != NTSTATUS.STATUS_SUCCESS)
            {
                throw ErrorMethods.GetIoExceptionForNTStatus(status);
            }
        }
        public static unsafe void ToUpperInvariant(ref UNICODE_STRING value)
        {
            NTSTATUS status = Imports.RtlUpcaseUnicodeString(
                (UNICODE_STRING *)Structs.AddressOf(ref value), (UNICODE_STRING *)Structs.AddressOf(ref value), false);

            if (!ErrorMacros.NT_SUCCESS(status))
            {
                ErrorMethods.GetIoExceptionForNTStatus(status);
            }
        }
Exemple #6
0
        /// <summary>
        /// Get the access rights applied to the given file handle.
        /// </summary>
        public unsafe static FileAccessRights GetRights(SafeFileHandle fileHandle)
        {
            FILE_ACCESS_INFORMATION access = new FILE_ACCESS_INFORMATION();
            NTSTATUS result = Imports.NtQueryInformationFile(fileHandle, out _,
                                                             &access, (uint)sizeof(FILE_ACCESS_INFORMATION), FileInformationClass.FileAccessInformation);

            if (result != NTSTATUS.STATUS_SUCCESS)
            {
                throw ErrorMethods.GetIoExceptionForNTStatus(result);
            }
            return(access.AccessFlags);
        }
Exemple #7
0
        unsafe private static void GetFileInformation(SafeFileHandle fileHandle, FileInformationClass fileInformationClass, void *value, uint size)
        {
            NTSTATUS status = Imports.NtQueryInformationFile(
                FileHandle: fileHandle,
                IoStatusBlock: out _,
                FileInformation: value,
                Length: size,
                FileInformationClass: fileInformationClass);

            if (status != NTSTATUS.STATUS_SUCCESS)
            {
                throw ErrorMethods.GetIoExceptionForNTStatus(status);
            }
        }
        public static LsaHandle LsaOpenLocalPolicy(PolicyAccessRights access)
        {
            LSA_OBJECT_ATTRIBUTES attributes = new LSA_OBJECT_ATTRIBUTES();
            LsaHandle             handle;
            NTSTATUS status;

            unsafe
            {
                status = Imports.LsaOpenPolicy(null, &attributes, access, out handle);
            }

            if (status != NTSTATUS.STATUS_SUCCESS)
            {
                throw ErrorMethods.GetIoExceptionForNTStatus(status);
            }

            return(handle);
        }
        // Windows Kernel Architecture Internals
        // http://research.microsoft.com/en-us/um/redmond/events/wincore2010/Dave_Probert_1.pdf

        // Object Manager Routines (kernel-mode file systems and file system filter drivers)
        // https://msdn.microsoft.com/en-us/library/windows/hardware/ff550969.aspx
        // https://msdn.microsoft.com/en-us/library/windows/hardware/ff557759.aspx

        // Managing Kernel Objects
        // https://msdn.microsoft.com/en-us/library/windows/hardware/ff554383.aspx

        /// <summary>
        /// Open a handle to a directory object at the given NT path.
        /// </summary>
        public static DirectoryObjectHandle OpenDirectoryObject(
            string path,
            DirectoryObjectRights desiredAccess = DirectoryObjectRights.Query)
        {
            return((DirectoryObjectHandle)OpenObjectHelper(path, (attributes) =>
            {
                NTSTATUS status = Imports.NtOpenDirectoryObject(
                    DirectoryHandle: out var directory,
                    DesiredAccess: desiredAccess,
                    ObjectAttributes: ref attributes);

                if (status != NTSTATUS.STATUS_SUCCESS)
                {
                    throw ErrorMethods.GetIoExceptionForNTStatus(status, path);
                }

                return directory;
            }));
Exemple #10
0
        public unsafe static string QueryKeyName(RegistryKeyHandle key)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                NTSTATUS status;
                uint resultLength;
                while ((status = Imports.NtQueryKey(key, KEY_INFORMATION_CLASS.KeyNameInformation, buffer.VoidPointer, (uint)buffer.ByteCapacity, out resultLength))
                       == NTSTATUS.STATUS_BUFFER_TOO_SMALL || status == NTSTATUS.STATUS_BUFFER_OVERFLOW)
                {
                    buffer.EnsureByteCapacity(resultLength);
                }

                if (status != NTSTATUS.STATUS_SUCCESS)
                {
                    ErrorMethods.GetIoExceptionForNTStatus(status);
                }

                return ((KEY_NAME_INFORMATION *)buffer.VoidPointer)->Name.CreateString();
            }));
        }
Exemple #11
0
        public unsafe static IntPtr CreateFileRelative(
            ReadOnlySpan <char> path,
            IntPtr rootDirectory,
            CreateDisposition createDisposition,
            DesiredAccess desiredAccess       = DesiredAccess.GenericReadWrite | DesiredAccess.Synchronize,
            ShareModes shareAccess            = ShareModes.ReadWrite,
            FileAttributes fileAttributes     = FileAttributes.None,
            CreateOptions createOptions       = CreateOptions.SynchronousIoNonalert,
            ObjectAttributes objectAttributes = ObjectAttributes.CaseInsensitive)
        {
            fixed(char *c = &path.DangerousGetPinnableReference())
            {
                UNICODE_STRING    name       = new UNICODE_STRING(c, path.Length);
                OBJECT_ATTRIBUTES attributes = new OBJECT_ATTRIBUTES(
                    &name,
                    objectAttributes,
                    rootDirectory,
                    null,
                    null);

                NTSTATUS status = Imports.NtCreateFile(
                    out IntPtr handle,
                    desiredAccess,
                    ref attributes,
                    out IO_STATUS_BLOCK statusBlock,
                    AllocationSize: null,
                    FileAttributes: fileAttributes,
                    ShareAccess: shareAccess,
                    CreateDisposition: createDisposition,
                    CreateOptions: createOptions,
                    EaBuffer: null,
                    EaLength: 0);

                if (status != NTSTATUS.STATUS_SUCCESS)
                {
                    throw ErrorMethods.GetIoExceptionForNTStatus(status, path.ToString());
                }

                return(handle);
            }
        }
Exemple #12
0
        private unsafe static string GetFileInformationString(SafeFileHandle fileHandle, FileInformationClass fileInformationClass)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                NTSTATUS status = NTSTATUS.STATUS_BUFFER_OVERFLOW;

                // Start with MAX_PATH
                uint byteLength = 260 * sizeof(char);

                FILE_NAME_INFORMATION *value = null;

                while (status == NTSTATUS.STATUS_BUFFER_OVERFLOW)
                {
                    // Add space for the FileNameLength
                    buffer.EnsureByteCapacity(byteLength + sizeof(uint));

                    status = Imports.NtQueryInformationFile(
                        FileHandle: fileHandle,
                        IoStatusBlock: out _,
                        FileInformation: buffer.VoidPointer,
                        Length: checked ((uint)buffer.ByteCapacity),
                        FileInformationClass: fileInformationClass);

                    if (status == NTSTATUS.STATUS_SUCCESS || status == NTSTATUS.STATUS_BUFFER_OVERFLOW)
                    {
                        value = (FILE_NAME_INFORMATION *)buffer.VoidPointer;
                        byteLength = value->FileNameLength;
                    }
                }

                if (status != NTSTATUS.STATUS_SUCCESS)
                {
                    throw ErrorMethods.GetIoExceptionForNTStatus(status);
                }

                return value->FileName.CreateString();
            }));
        }
Exemple #13
0
        /// <summary>
        /// Gets the key's value data directly from NtEnumerateValueKey. This is slightly faster
        /// and uses less memory, but only works for keys in the local machine registry and does
        /// not work with performance keys (such as HKEY_PERFORMANCE_DATA).
        ///
        /// This also doesn't give the same results for "special" (HKCR) keys that are normally
        /// redirected to user specific settings by RegEnumValue.
        /// </summary>
        /// <param name="filterTo">
        /// Only return data of the given type, or REG_NONE for all types.
        /// </param>
        /// <remarks>
        /// RegEnumValue doesn't map directly to NtEnumerateValueKey and requires allocating a
        /// temporary buffer for *each* invocation- making the direct call here avoids this extra
        /// buffer.
        /// </remarks>
        public unsafe static IEnumerable <object> GetValueDataDirect(RegistryKeyHandle key, RegistryValueType filterTo = RegistryValueType.REG_NONE)
        {
            List <object> data = new List <object>();

            BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                NTSTATUS status;
                while ((status = Imports.NtEnumerateValueKey(
                            key,
                            (uint)data.Count,
                            KEY_VALUE_INFORMATION_CLASS.KeyValuePartialInformation,
                            buffer.VoidPointer,
                            checked ((uint)buffer.ByteCapacity),
                            out uint resultLength)) != NTSTATUS.STATUS_NO_MORE_ENTRIES)
                {
                    switch (status)
                    {
                    case NTSTATUS.STATUS_SUCCESS:
                        KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer.VoidPointer;
                        if (filterTo == RegistryValueType.REG_NONE || (*info).Type == filterTo)
                        {
                            data.Add(ReadValue(&(*info).Data, (*info).DataLength, (*info).Type));
                        }
                        break;

                    case NTSTATUS.STATUS_BUFFER_OVERFLOW:
                    case NTSTATUS.STATUS_BUFFER_TOO_SMALL:
                        buffer.EnsureByteCapacity(resultLength);
                        break;

                    default:
                        throw ErrorMethods.GetIoExceptionForNTStatus(status);
                    }
                }
            });

            return(data);
        }
Exemple #14
0
        /// <summary>
        /// Gets the key's value names directly from NtEnumerateValueKey. This is slightly faster
        /// and uses less memory, but only works for keys in the local machine registry and does
        /// not work with performance keys (such as HKEY_PERFORMANCE_DATA).
        ///
        /// This also doesn't give the same results for "special" (HKCR) keys that are normally
        /// redirected to user specific settings by RegEnumValue.
        /// </summary>
        /// <param name="filterTo">
        /// Only return names that have the given type, or REG_NONE for all types.
        /// </param>
        /// <remarks>
        /// RegEnumValue doesn't map directly to NtEnumerateValueKey and requires allocating a
        /// temporary buffer for *each* invocation- making the direct call here avoids this extra
        /// buffer.
        /// </remarks>
        public unsafe static IEnumerable <string> GetValueNamesDirect(RegistryKeyHandle key, RegistryValueType filterTo = RegistryValueType.REG_NONE)
        {
            List <string> names = new List <string>();

            BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                NTSTATUS status;
                while ((status = Imports.NtEnumerateValueKey(
                            key,
                            (uint)names.Count,
                            KEY_VALUE_INFORMATION_CLASS.KeyValueBasicInformation,
                            buffer.VoidPointer,
                            checked ((uint)buffer.ByteCapacity),
                            out uint resultLength)) != NTSTATUS.STATUS_NO_MORE_ENTRIES)
                {
                    switch (status)
                    {
                    case NTSTATUS.STATUS_SUCCESS:
                        KEY_VALUE_BASIC_INFORMATION *info = (KEY_VALUE_BASIC_INFORMATION *)buffer.VoidPointer;
                        if (filterTo == RegistryValueType.REG_NONE || info->Type == filterTo)
                        {
                            names.Add(info->Name.CreateString());
                        }
                        break;

                    case NTSTATUS.STATUS_BUFFER_OVERFLOW:
                    case NTSTATUS.STATUS_BUFFER_TOO_SMALL:
                        buffer.EnsureByteCapacity(resultLength);
                        break;

                    default:
                        throw ErrorMethods.GetIoExceptionForNTStatus(status);
                    }
                }
            });

            return(names);
        }