/// <summary>
        /// Create and initialize a Server Silo,
        /// </summary>
        /// <param name="root_dir_flags">Flags for root directory.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <param name="system_root">Path to the system root.</param>
        /// <param name="delete_event">Event to signal when silo deleted.</param>
        /// <param name="downlevel_container">True if a downlevel container.</param>
        /// <returns>The Job object.</returns>
        public static NtResult <NtJob> CreateServerSilo(SiloObjectRootDirectoryControlFlags root_dir_flags, string system_root, NtEvent delete_event, bool downlevel_container, bool throw_on_error)
        {
            using (var job = CreateSilo(root_dir_flags, throw_on_error))
            {
                if (!job.IsSuccess)
                {
                    return(job);
                }

                NtStatus status = job.Result.SetSiloSystemRoot(system_root, throw_on_error);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <NtJob>(throw_on_error));
                }

                var silo_dir = job.Result.QuerySiloRootDirectory(throw_on_error);
                if (!silo_dir.IsSuccess)
                {
                    return(silo_dir.Cast <NtJob>());
                }

                string device_path = $@"{silo_dir.Result}\Device";

                using (var device_dir = NtDirectory.Open(@"\Device", null, DirectoryAccessRights.MaximumAllowed, throw_on_error))
                {
                    if (!device_dir.IsSuccess)
                    {
                        return(device_dir.Cast <NtJob>());
                    }
                    using (var obja = new ObjectAttributes(device_path, AttributeFlags.CaseInsensitive | AttributeFlags.Permanent | AttributeFlags.OpenIf))
                    {
                        using (var dir = NtDirectory.Create(obja, DirectoryAccessRights.MaximumAllowed, device_dir.Result, throw_on_error))
                        {
                            if (!dir.IsSuccess)
                            {
                                return(dir.Cast <NtJob>());
                            }
                        }
                    }
                }

                status = job.Result.InitializeServerSilo(delete_event, downlevel_container, throw_on_error);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <NtJob>(throw_on_error));
                }
                return(job.Result.Duplicate().CreateResult());
            }
        }
示例#2
0
        /// <summary>
        /// Query a value by name
        /// </summary>
        /// <param name="value_name">The name of the value</param>
        /// <returns>The value information</returns>
        /// <exception cref="NtException">Thrown on error.</exception>
        public NtKeyValue QueryValue(string value_name)
        {
            UnicodeString name        = new UnicodeString(value_name);
            int           return_len  = 0;
            int           query_count = 0;

            while (query_count < 64)
            {
                using (var info = new SafeStructureInOutBuffer <KeyValuePartialInformation>(return_len, false))
                {
                    NtStatus status = NtSystemCalls.NtQueryValueKey(Handle, name, KeyValueInformationClass.KeyValuePartialInformation,
                                                                    info, info.Length, out return_len);
                    if (status.IsSuccess())
                    {
                        KeyValuePartialInformation result = info.Result;
                        return(new NtKeyValue(value_name, info.Result.Type, info.Data.ReadBytes(result.DataLength), result.TitleIndex));
                    }
                    if (status != NtStatus.STATUS_BUFFER_OVERFLOW && status != NtStatus.STATUS_BUFFER_TOO_SMALL)
                    {
                        status.ToNtException();
                    }
                    ;
                }
                query_count++;
            }
            throw new NtException(NtStatus.STATUS_BUFFER_TOO_SMALL);
        }
示例#3
0
        /// <summary>
        /// Query the image path from a process ID.
        /// </summary>
        /// <param name="pid">The ID of the process.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The image path.</returns>
        /// <remarks>This method can be called without any permissions on the process.</remarks>
        public static NtResult <string> GetProcessIdImagePath(int pid, bool throw_on_error)
        {
            var info = new SystemProcessIdInformation()
            {
                ProcessId = new IntPtr(pid)
            };

            using (var buffer = info.ToBuffer())
            {
                NtStatus status = _system_info_object.QueryInformation(
                    SystemInformationClass.SystemProcessIdInformation,
                    buffer, out int length);
                if (status.IsSuccess())
                {
                    return(new NtResult <string>(NtStatus.STATUS_SUCCESS, string.Empty));
                }
                if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH)
                {
                    return(status.CreateResultFromError <string>(throw_on_error));
                }

                using (var str = new UnicodeStringAllocated(buffer.Result.ImageName.MaximumLength))
                {
                    info = new SystemProcessIdInformation()
                    {
                        ProcessId = new IntPtr(pid), ImageName = str.String
                    };
                    return(Query(SystemInformationClass.SystemProcessIdInformation,
                                 info, throw_on_error).Map(r => r.ImageName.ToString()));
                }
            }
        }
示例#4
0
        /// <summary>
        /// Query memory information for a process.
        /// </summary>
        /// <param name="process">The process to query.</param>
        /// <param name="base_address">The base address.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The memory information for the region.</returns>
        /// <exception cref="NtException">Thrown on error.</exception>
        public static NtResult <MemoryInformation> QueryMemoryInformation(SafeKernelObjectHandle process, long base_address, bool throw_on_error)
        {
            MemoryBasicInformation basic_info = new MemoryBasicInformation();
            string mapped_image_path          = string.Empty;

            using (var buffer = new SafeStructureInOutBuffer <MemoryBasicInformation>())
            {
                NtStatus status = NtSystemCalls.NtQueryVirtualMemory(process,
                                                                     new IntPtr(base_address), MemoryInformationClass.MemoryBasicInformation,
                                                                     buffer, buffer.LengthIntPtr, out IntPtr ret_length);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <MemoryInformation>(throw_on_error));
                }
                basic_info = buffer.Result;
            }

            if (basic_info.Type == MemoryType.Image || basic_info.Type == MemoryType.Mapped)
            {
                var name = QuerySectionName(process, base_address, false);
                if (name.IsSuccess)
                {
                    mapped_image_path = name.Result;
                }
            }

            return(new MemoryInformation(basic_info, mapped_image_path).CreateResult());
        }
        /// <summary>
        /// Enumerate all atoms.
        /// </summary>
        /// <returns>An enumeration of all atoms on the system.</returns>
        public static IEnumerable <NtAtom> GetAtoms()
        {
            int size = 1024;

            while (size < 5 * 1024 * 1024)
            {
                using (SafeStructureInOutBuffer <AtomTableInformation> buffer = new SafeStructureInOutBuffer <AtomTableInformation>(size, true))
                {
                    int      return_length;
                    NtStatus status = NtSystemCalls.NtQueryInformationAtom(0, AtomInformationClass.AtomTableInformation, buffer, buffer.Length, out return_length);
                    if (status.IsSuccess())
                    {
                        AtomTableInformation table = buffer.Result;
                        IntPtr data = buffer.Data.DangerousGetHandle();
                        for (int i = 0; i < table.NumberOfAtoms; ++i)
                        {
                            ushort atom = (ushort)Marshal.ReadInt16(data);
                            yield return(new NtAtom(atom));

                            data += 2;
                        }
                    }
                    else if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH)
                    {
                        throw new NtException(status);
                    }
                    size *= 2;
                }
            }
        }
示例#6
0
        private static IEnumerable <string> EnumNameList(SafeKernelObjectHandle handle)
        {
            int size = 522;

            for (int i = 0; i < 10; ++i)
            {
                using (var buffer = new SafeHGlobalBuffer(size))
                {
                    NtStatus status = NtSystemCalls.NtUserBuildNameList(handle, buffer.Length, buffer, out size);
                    if (!status.IsSuccess())
                    {
                        if (status == NtStatus.STATUS_BUFFER_TOO_SMALL)
                        {
                            continue;
                        }
                        status.ToNtException();
                    }
                    int total_count = buffer.Read <int>(4);
                    int offset      = 8;
                    while (total_count > 0)
                    {
                        string name = buffer.ReadNulTerminatedUnicodeString((ulong)offset);
                        yield return(name);

                        offset += (name.Length + 1) * 2;
                        total_count--;
                    }
                    yield break;
                }
            }
            throw new NtException(NtStatus.STATUS_NO_MEMORY);
        }
        /// <summary>
        /// Get a mitigation policy raw value
        /// </summary>
        /// <param name="policy">The policy to get</param>
        /// <returns>The raw policy value</returns>
        public int GetProcessMitigationPolicy(ProcessMitigationPolicy policy)
        {
            switch (policy)
            {
            case ProcessMitigationPolicy.ProcessDEPPolicy:
            case ProcessMitigationPolicy.ProcessReserved1Policy:
            case ProcessMitigationPolicy.ProcessMitigationOptionsMask:
                throw new ArgumentException("Invalid mitigation policy");
            }

            MitigationPolicy p = new MitigationPolicy();

            p.Policy = policy;

            using (var buffer = p.ToBuffer())
            {
                int      return_length;
                NtStatus status = NtSystemCalls.NtQueryInformationProcess(Handle, ProcessInfoClass.ProcessMitigationPolicy, buffer, buffer.Length, out return_length);
                if (!status.IsSuccess())
                {
                    if (status != NtStatus.STATUS_INVALID_PARAMETER && status != NtStatus.STATUS_NOT_SUPPORTED)
                    {
                        status.ToNtException();
                    }
                    return(0);
                }
                return(buffer.Result.Result);
            }
        }
        /// <summary>
        /// Retried LSA privilege data.
        /// </summary>
        /// <param name="system_name">The system containing the LSA instance.</param>
        /// <param name="keyname">The name of the key.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The private data as bytes.</returns>
        public static NtResult <byte[]> LsaRetrievePrivateData(string system_name, string keyname, bool throw_on_error)
        {
            if (keyname is null)
            {
                throw new ArgumentNullException(nameof(keyname));
            }

            using (var policy = SafeLsaHandle.OpenPolicy(system_name, Policy.LsaPolicyAccessRights.GetPrivateInformation, throw_on_error))
            {
                if (!policy.IsSuccess)
                {
                    return(policy.Cast <byte[]>());
                }
                NtStatus status = SecurityNativeMethods.LsaRetrievePrivateData(policy.Result,
                                                                               new UnicodeString(keyname), out SafeLsaMemoryBuffer data);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <byte[]>(throw_on_error));
                }
                using (data)
                {
                    data.Initialize <UnicodeStringOut>(1);
                    return(data.Read <UnicodeStringOut>(0).ToArray().CreateResult());
                }
            }
        }
示例#9
0
        private static IEnumerable <NtAtom> GetGlobalAtoms()
        {
            int size = 1024;

            while (size < 5 * 1024 * 1024)
            {
                using (var buffer = new SafeStructureInOutBuffer <AtomTableInformation>(size, true))
                {
                    NtStatus status = NtSystemCalls.NtQueryInformationAtom(0,
                                                                           AtomInformationClass.AtomTableInformation, buffer, buffer.Length, out int return_length);
                    if (status.IsSuccess())
                    {
                        AtomTableInformation table = buffer.Result;
                        IntPtr   data  = buffer.Data.DangerousGetHandle();
                        ushort[] atoms = new ushort[table.NumberOfAtoms];
                        buffer.Data.ReadArray(0, atoms, 0, atoms.Length);
                        return(atoms.Select(a => new NtAtom(a, true)).ToArray());
                    }
                    else if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH)
                    {
                        throw new NtException(status);
                    }
                    size *= 2;
                }
            }
            return(new NtAtom[0]);
        }
        private NtStatus ParseSecurityDescriptor(SafeBuffer buffer)
        {
            if (!NtRtl.RtlValidSecurityDescriptor(buffer))
            {
                return(NtStatus.STATUS_INVALID_SECURITY_DESCR);
            }

            Owner = QuerySid(buffer, NtRtl.RtlGetOwnerSecurityDescriptor);
            Group = QuerySid(buffer, NtRtl.RtlGetGroupSecurityDescriptor);
            Dacl  = QueryAcl(buffer, NtRtl.RtlGetDaclSecurityDescriptor);
            Sacl  = QueryAcl(buffer, NtRtl.RtlGetSaclSecurityDescriptor);
            NtStatus status = NtRtl.RtlGetControlSecurityDescriptor(buffer,
                                                                    out SecurityDescriptorControl control, out uint revision);

            if (!status.IsSuccess())
            {
                return(status);
            }
            if (NtRtl.RtlGetSecurityDescriptorRMControl(buffer, out byte rm_control))
            {
                RmControl = rm_control;
            }
            Control  = control;
            Revision = revision;

            return(NtStatus.STATUS_SUCCESS);
        }
示例#11
0
        private static SafeStructureInOutBuffer <T> QueryObject <T>(SafeKernelObjectHandle handle, ObjectInformationClass object_info) where T : new()
        {
            SafeStructureInOutBuffer <T> ret = null;
            NtStatus status = NtStatus.STATUS_BUFFER_TOO_SMALL;

            try
            {
                int return_length;
                status = NtSystemCalls.NtQueryObject(handle, object_info, IntPtr.Zero, 0, out return_length);
                if ((status != NtStatus.STATUS_BUFFER_TOO_SMALL) && (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH))
                {
                    status.ToNtException();
                }
                if (return_length == 0)
                {
                    ret = new SafeStructureInOutBuffer <T>();
                }
                else
                {
                    ret = new SafeStructureInOutBuffer <T>(return_length, false);
                }
                status = NtSystemCalls.NtQueryObject(handle, object_info, ret.DangerousGetHandle(), ret.Length, out return_length);
                status.ToNtException();
            }
            finally
            {
                if (ret != null && !status.IsSuccess())
                {
                    ret.Close();
                    ret = null;
                }
            }
            return(ret);
        }
示例#12
0
        private static NtResult <SafeStructureInOutBuffer <T> > QueryObject <T>(SafeKernelObjectHandle handle,
                                                                                ObjectInformationClass object_info, bool throw_on_error) where T : new()
        {
            SafeStructureInOutBuffer <T> ret = null;
            NtStatus status = NtStatus.STATUS_BUFFER_TOO_SMALL;

            try
            {
                status = NtSystemCalls.NtQueryObject(handle, object_info, SafeHGlobalBuffer.Null, 0, out int return_length);
                if ((status != NtStatus.STATUS_BUFFER_TOO_SMALL) && (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH))
                {
                    return(status.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error));
                }

                if (return_length == 0)
                {
                    ret = new SafeStructureInOutBuffer <T>();
                }
                else
                {
                    ret = new SafeStructureInOutBuffer <T>(return_length, false);
                }
                status = NtSystemCalls.NtQueryObject(handle, object_info, ret, ret.Length, out return_length);
                return(status.CreateResult(throw_on_error, () => ret));
            }
            finally
            {
                if (ret != null && !status.IsSuccess())
                {
                    ret.Close();
                    ret = null;
                }
            }
        }
 /// <summary>
 /// Convert an NtStatus to an exception if the status is an error and throw_on_error is true.
 /// </summary>
 /// <param name="status">The NtStatus</param>
 /// <param name="throw_on_error">True to throw an exception onerror.</param>
 /// <returns>The original NtStatus if not thrown</returns>
 /// <exception cref="NtException">Thrown if status is an error and throw_on_error is true.</exception>
 public static NtStatus ToNtException(this NtStatus status, bool throw_on_error)
 {
     if (throw_on_error && !status.IsSuccess())
     {
         throw new NtException(status);
     }
     return(status);
 }
示例#14
0
        /// <summary>
        /// Sleep the current thread
        /// </summary>
        /// <param name="alertable">Set if the thread should be alertable</param>
        /// <param name="delay">The delay, negative values indicate relative times.</param>
        /// <returns>True if the thread was alerted before the delay expired.</returns>
        public static bool Sleep(bool alertable, long delay)
        {
            NtStatus status = NtSystemCalls.NtDelayExecution(alertable, new LargeInteger(delay));
            if (!status.IsSuccess())
            {
                throw new NtException(status);                
            }

            return status == NtStatus.STATUS_ALERTED;
        }
        /// <summary>
        /// Initialize a Silo,
        /// </summary>
        /// <param name="root_dir_flags">Flags for root directory.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The NT status code.</returns>
        public NtStatus InitializeSilo(SiloObjectRootDirectoryControlFlags root_dir_flags, bool throw_on_error)
        {
            NtStatus status = SetLimitFlags(JobObjectLimitFlags.Application, throw_on_error);

            if (!status.IsSuccess())
            {
                return(status);
            }
            status = CreateSilo(throw_on_error);
            if (!status.IsSuccess())
            {
                return(status);
            }
            status = AssignProcessPseudoHandle(throw_on_error);
            if (!status.IsSuccess())
            {
                return(status);
            }
            return(SetSiloObjectRootDirectory(root_dir_flags, throw_on_error));
        }
        /// <summary>
        /// Create an NT result object. If status is successful then call function otherwise use default value.
        /// </summary>
        /// <typeparam name="T">The result type.</typeparam>
        /// <param name="status">The associated status case.</param>
        /// <param name="throw_on_error">Throw an exception on error.</param>
        /// <param name="create_func">Function to call to create an instance of the result</param>
        /// <returns>The created result.</returns>
        internal static NtResult <T> CreateResult <T>(this NtStatus status, bool throw_on_error, Func <NtStatus, T> create_func)
        {
            if (status.IsSuccess())
            {
                return(new NtResult <T>(status, create_func(status)));
            }

            if (throw_on_error)
            {
                throw new NtException(status);
            }

            return(new NtResult <T>(status, default(T)));
        }
示例#17
0
 internal NtStatus CompleteCall(NtStatus status)
 {
     if (status == NtStatus.STATUS_PENDING)
     {
         if (WaitForComplete())
         {
             status = _io_status.Result.Status;
         }
     }
     else if (status.IsSuccess())
     {
         _result = _io_status.Result;
     }
     return(status);
 }
        /// <summary>
        /// Convert a DOS filename to an NT filename and get as an ObjectAttributes structure
        /// </summary>
        /// <param name="filename">The DOS filename.</param>
        /// <param name="attributes">The object attribute flags.</param>
        /// <param name="sqos">An optional security quality of service.</param>
        /// <param name="security_descriptor">An optional security descriptor.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The object attributes</returns>
        public static NtResult <ObjectAttributes> DosFileNameToObjectAttributes(string filename, AttributeFlags attributes,
                                                                                SecurityQualityOfService sqos, SecurityDescriptor security_descriptor, bool throw_on_error)
        {
            if (filename == null)
            {
                throw new ArgumentNullException("filename");
            }

            UnicodeStringOut nt_name       = new UnicodeStringOut();
            RtlRelativeName  relative_name = new RtlRelativeName();

            try
            {
                NtStatus status = NtRtl.RtlDosPathNameToRelativeNtPathName_U_WithStatus(filename, out nt_name,
                                                                                        out IntPtr short_path, relative_name);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <ObjectAttributes>(throw_on_error));
                }
                string final_name;
                SafeKernelObjectHandle root = SafeKernelObjectHandle.Null;

                if (relative_name.RelativeName.Buffer != IntPtr.Zero)
                {
                    final_name = relative_name.RelativeName.ToString();
                    root       = new SafeKernelObjectHandle(relative_name.ContainingDirectory, false);
                }
                else
                {
                    final_name = nt_name.ToString();
                }

                return(status.CreateResult(false, () =>
                                           new ObjectAttributes(final_name, attributes, root, sqos, security_descriptor)));
            }
            finally
            {
                if (nt_name.Buffer != IntPtr.Zero)
                {
                    NtRtl.RtlFreeUnicodeString(ref nt_name);
                }

                if (relative_name.RelativeName.Buffer != IntPtr.Zero)
                {
                    NtRtl.RtlReleaseRelativeName(relative_name);
                }
            }
        }
        /// <summary>
        /// Get the source of inherited ACEs.
        /// </summary>
        /// <param name="name">The name of the resource.</param>
        /// <param name="type">The type of the resource.</param>
        /// <param name="container">Whether the resource is a container.</param>
        /// <param name="object_types">Optional list of object types.</param>
        /// <param name="security_descriptor">The security descriptor for the resource.</param>
        /// <param name="sacl">True to check the SACL otherwise checks the DACL.</param>
        /// <param name="generic_mapping">Generic mapping for the resource.</param>
        /// <param name="query_security">Query security descriptors for sources.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The list of inheritance sources.</returns>
        public static NtResult <IEnumerable <SecurityDescriptorInheritanceSource> > GetInheritanceSource(
            string name,
            SeObjectType type,
            bool container,
            Guid[] object_types,
            SecurityDescriptor security_descriptor,
            bool sacl,
            GenericMapping generic_mapping,
            bool query_security,
            bool throw_on_error)
        {
            Acl acl = sacl ? security_descriptor.Sacl : security_descriptor.Dacl;

            if (acl == null || acl.NullAcl)
            {
                return(NtStatus.STATUS_INVALID_ACL.CreateResultFromError <IEnumerable <SecurityDescriptorInheritanceSource> >(throw_on_error));
            }

            using (var list = new DisposableList())
            {
                SafeGuidArrayBuffer guids = SafeGuidArrayBuffer.Null;
                if (object_types?.Length > 0)
                {
                    guids = list.AddResource(new SafeGuidArrayBuffer(object_types));
                }

                NtType native_type = GetNativeType(type);

                INHERITED_FROM[] inherited_from = new INHERITED_FROM[acl.Count];
                NtStatus         status         = NtStatus.STATUS_INVALID_PARAMETER;
                try
                {
                    status = Win32NativeMethods.GetInheritanceSource(name, type, sacl ? SecurityInformation.Sacl : SecurityInformation.Dacl,
                                                                     container, guids, guids.Count, acl.ToByteArray(), IntPtr.Zero, ref generic_mapping, inherited_from).MapDosErrorToStatus();
                    return(status.CreateResult(throw_on_error, () => (IEnumerable <SecurityDescriptorInheritanceSource>)inherited_from
                                               .Select((s, i) => new SecurityDescriptorInheritanceSource(acl[i], s, type,
                                                                                                         native_type, container, query_security, sacl)).Where(s => s.Depth != -1).ToArray()));
                }
                finally
                {
                    if (status.IsSuccess())
                    {
                        Win32NativeMethods.FreeInheritedFromArray(inherited_from, (ushort)inherited_from.Length, IntPtr.Zero);
                    }
                }
            }
        }
示例#20
0
 private static NtStatus Decompress(RtlCompressionFormat format, byte[] compressed_buffer, byte[] uncompressed_buffer, out int final_size)
 {
     if (format == RtlCompressionFormat.XPRESS_HUFF)
     {
         NtStatus status = NtRtl.RtlGetCompressionWorkSpaceSize(format, out int compress_size, out int fragment_size);
         if (!status.IsSuccess())
         {
             final_size = 0;
             return(status);
         }
         byte[] workspace = new byte[compress_size];
         return(NtRtl.RtlDecompressBufferEx(format, uncompressed_buffer, uncompressed_buffer.Length,
                                            compressed_buffer, compressed_buffer.Length, out final_size, workspace));
     }
     return(NtRtl.RtlDecompressBuffer(format, uncompressed_buffer, uncompressed_buffer.Length,
                                      compressed_buffer, compressed_buffer.Length, out final_size));
 }
        /// <summary>
        /// Retrieve LSA privilege data.
        /// </summary>
        /// <param name="keyname">The name of the key.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The private data as bytes.</returns>
        public NtResult <byte[]> RetrievePrivateData(string keyname, bool throw_on_error)
        {
            if (keyname is null)
            {
                throw new ArgumentNullException(nameof(keyname));
            }

            NtStatus status = SecurityNativeMethods.LsaRetrievePrivateData(Handle,
                                                                           new UnicodeString(keyname), out SafeLsaMemoryBuffer data);

            if (!status.IsSuccess())
            {
                return(status.CreateResultFromError <byte[]>(throw_on_error));
            }
            using (data)
            {
                return(data.GetUnicodeString().ToArray().CreateResult());
            }
        }
示例#22
0
 internal async Task <NtStatus> CompleteCallAsync(NtStatus status, CancellationToken token)
 {
     try {
         if (status == NtStatus.STATUS_PENDING)
         {
             if (await WaitForCompleteAsync(token))
             {
                 return(_result.Status);
             }
         }
         else if (status.IsSuccess())
         {
             _result = _io_status.Result;
         }
         return(status);
     } catch (TaskCanceledException) {
         // Cancel and then rethrow.
         Cancel();
         throw;
     }
 }
示例#23
0
        /// <summary>
        /// Enumerate window handles.
        /// </summary>
        /// <param name="desktop">Desktop containing the Windows. Optional.</param>
        /// <param name="parent">The parent Window. Optional.</param>
        /// <param name="enum_children">True to enumerate child Windows.</param>
        /// <param name="hide_immersive">Hide immersive Windows.</param>
        /// <param name="thread_id">The thread ID that owns the Window.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The enumerated Window Handles.</returns>
        public static NtResult <IEnumerable <NtWindow> > GetWindows(NtDesktop desktop, NtWindow parent,
                                                                    bool enum_children, bool hide_immersive, int thread_id, bool throw_on_error)
        {
            int count = 64;

            while (true)
            {
                IntPtr[] handles = new IntPtr[count];
                NtStatus status  = NtSystemCalls.NtUserBuildHwndList(desktop.GetHandle(), parent.Handle, enum_children,
                                                                     hide_immersive, thread_id, handles.Length, handles, out int required_count);
                if (status.IsSuccess())
                {
                    return(handles.Take(required_count).Select(i => new NtWindow(i)).CreateResult());
                }
                if (status != NtStatus.STATUS_BUFFER_TOO_SMALL || count > required_count)
                {
                    return(status.CreateResultFromError <IEnumerable <NtWindow> >(throw_on_error));
                }
                count = required_count;
            }
        }
        /// <summary>
        /// Enable a provider.
        /// </summary>
        /// <param name="provider_id">The GUID of the provider.</param>
        /// <param name="level">The level for the events.</param>
        /// <param name="match_any_keyword">Any keywords to match.</param>
        /// <param name="match_all_keyword">All keywords to match.</param>
        /// <param name="timeout">The timeout.</param>
        /// <param name="descriptors">List of optional descriptors.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The resulting status code.</returns>
        public NtStatus EnableProvider(Guid provider_id, EventTraceLevel level, ulong match_any_keyword,
                                       ulong match_all_keyword, int timeout, IEnumerable <EventFilterDescriptor> descriptors, bool throw_on_error)
        {
            var ds = descriptors.Select(d => new EVENT_FILTER_DESCRIPTOR()
            {
                Ptr  = d.Ptr.ToInt64(),
                Size = d.Size,
                Type = d.Type
            }).ToArray();

            using (var buffer = ds.ToBuffer())
            {
                ENABLE_TRACE_PARAMETERS enable_trace = new ENABLE_TRACE_PARAMETERS
                {
                    Version          = 2,
                    SourceId         = SessionGuid,
                    EnableFilterDesc = buffer.DangerousGetHandle(),
                    FilterDescCount  = ds.Length
                };

                NtStatus status = Win32NativeMethods.EnableTraceEx2(
                    _handle,
                    ref provider_id,
                    EventControlCode.EnableProvider,
                    level,
                    match_any_keyword,
                    match_all_keyword,
                    timeout,
                    enable_trace
                    ).MapDosErrorToStatus().ToNtException(throw_on_error);
                if (status.IsSuccess())
                {
                    _providers.Add(new EnabledProvider()
                    {
                        ProviderId = provider_id, Level = level
                    });
                }
                return(status);
            }
        }
示例#25
0
        private static NtResult <NtToken> LsaLogonUser(SecurityLogonType type, string auth_package, string origin_name,
                                                       SafeBuffer buffer, IEnumerable <UserGroup> local_groups, bool throw_on_error)
        {
            using (var list = new DisposableList())
            {
                var hlsa = list.AddResource(SafeLsaLogonHandle.Connect(throw_on_error));
                if (!hlsa.IsSuccess)
                {
                    return(hlsa.Cast <NtToken>());
                }
                NtStatus status = SecurityNativeMethods.LsaLookupAuthenticationPackage(
                    hlsa.Result, new LsaString(auth_package), out uint auth_pkg);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <NtToken>(throw_on_error));
                }

                var groups = local_groups == null ? SafeTokenGroupsBuffer.Null
                    : list.AddResource(SafeTokenGroupsBuffer.Create(local_groups));

                TOKEN_SOURCE tokenSource = new TOKEN_SOURCE("NT.NET");
                SecurityNativeMethods.AllocateLocallyUniqueId(out tokenSource.SourceIdentifier);
                QUOTA_LIMITS quota_limits = new QUOTA_LIMITS();
                return(SecurityNativeMethods.LsaLogonUser(hlsa.Result, new LsaString(origin_name),
                                                          type, auth_pkg, buffer, buffer.GetLength(), groups,
                                                          tokenSource, out SafeLsaReturnBufferHandle profile,
                                                          out int cbProfile, out Luid logon_id, out SafeKernelObjectHandle token_handle,
                                                          quota_limits, out NtStatus subStatus).CreateResult(throw_on_error, () =>
                {
                    using (profile)
                    {
                        return NtToken.FromHandle(token_handle);
                    }
                }));
            }
        }
        /// <summary>
        /// Start the new process
        /// </summary>
        /// <param name="image_path">The image path to the file to execute</param>
        /// <returns>The result of the process creation</returns>
        public CreateUserProcessResult Start(string image_path)
        {
            if (image_path == null)
            {
                throw new System.ArgumentNullException("image_path");
            }

            IntPtr process_params = CreateProcessParameters(ImagePath ?? image_path, DllPath, CurrentDirectory,
                                                            CommandLine, Environment, WindowTitle, DesktopInfo, ShellInfo, RuntimeData, 1);
            List <ProcessAttribute> attrs = new List <ProcessAttribute>();

            try
            {
                ProcessCreateInfo      create_info = new ProcessCreateInfo();
                SafeKernelObjectHandle process_handle;
                SafeKernelObjectHandle thread_handle;

                attrs.Add(ProcessAttribute.ImageName(image_path));
                SafeStructureInOutBuffer <SectionImageInformation> image_info = new SafeStructureInOutBuffer <SectionImageInformation>();
                attrs.Add(ProcessAttribute.ImageInfo(image_info));
                SafeStructureInOutBuffer <ClientId> client_id = new SafeStructureInOutBuffer <ClientId>();
                attrs.Add(ProcessAttribute.ClientId(client_id));
                attrs.AddRange(AdditionalAttributes);
                if (ParentProcess != null)
                {
                    attrs.Add(ProcessAttribute.ParentProcess(ParentProcess.Handle));
                }

                if (RestrictChildProcess || OverrideRestrictChildProcess)
                {
                    attrs.Add(ProcessAttribute.ChildProcess(RestrictChildProcess, OverrideRestrictChildProcess));
                }

                ProcessAttributeList attr_list = new ProcessAttributeList(attrs);

                create_info.Data.InitFlags = InitFlags | ProcessCreateInitFlag.WriteOutputOnExit;
                create_info.Data.ProhibitedImageCharacteristics = ProhibitedImageCharacteristics;
                create_info.Data.AdditionalFileAccess           = AdditionalFileAccess;

                NtStatus status = NtSystemCalls.NtCreateUserProcess(
                    out process_handle, out thread_handle,
                    ProcessAccessRights.MaximumAllowed, ThreadAccessRights.MaximumAllowed,
                    null, null, ProcessFlags,
                    ThreadFlags, process_params, create_info, attr_list);

                if (!status.IsSuccess() && !ReturnOnError)
                {
                    // Close handles which come from errors
                    switch (create_info.State)
                    {
                    case ProcessCreateState.FailOnSectionCreate:
                        NtSystemCalls.NtClose(create_info.Data.FileHandle);
                        break;

                    case ProcessCreateState.FailExeName:
                        NtSystemCalls.NtClose(create_info.Data.IFEOKey);
                        break;
                    }

                    status.ToNtException();
                }

                if (create_info.State == ProcessCreateState.Success)
                {
                    return(new CreateUserProcessResult(process_handle, thread_handle,
                                                       create_info.Data, image_info.Result, client_id.Result, TerminateOnDispose));
                }
                else
                {
                    return(new CreateUserProcessResult(status, create_info.Data, create_info.State));
                }
            }
            finally
            {
                NtRtl.RtlDestroyProcessParameters(process_params);
                foreach (ProcessAttribute attr in attrs)
                {
                    attr.Dispose();
                }
            }
        }
示例#27
0
        /// <summary>
        /// Start the new process
        /// </summary>
        /// <param name="image_path">The image path to the file to execute</param>
        /// <returns>The result of the process creation</returns>
        public CreateUserProcessResult Start(string image_path)
        {
            if (image_path == null)
            {
                throw new ArgumentNullException("image_path");
            }

            using (var process_params = SafeProcessParametersBuffer.Create(ConfigImagePath ?? image_path, DllPath, CurrentDirectory,
                                                                           CommandLine, Environment, WindowTitle, DesktopInfo, ShellInfo, RuntimeData, CreateProcessParametersFlags.Normalize)) {
                using (var attrs = new DisposableList <ProcessAttribute>()) {
                    ProcessCreateInfo create_info = new ProcessCreateInfo();

                    attrs.Add(ProcessAttribute.ImageName(image_path));
                    SafeStructureInOutBuffer <SectionImageInformation> image_info = new SafeStructureInOutBuffer <SectionImageInformation>();
                    attrs.Add(ProcessAttribute.ImageInfo(image_info));
                    SafeStructureInOutBuffer <ClientId> client_id = new SafeStructureInOutBuffer <ClientId>();
                    attrs.Add(ProcessAttribute.ClientId(client_id));
                    attrs.AddRange(AdditionalAttributes);
                    if (ParentProcess != null)
                    {
                        attrs.Add(ProcessAttribute.ParentProcess(ParentProcess.Handle));
                    }

                    if (RestrictChildProcess || OverrideRestrictChildProcess)
                    {
                        attrs.Add(ProcessAttribute.ChildProcess(RestrictChildProcess, OverrideRestrictChildProcess));
                    }

                    if (Token != null)
                    {
                        attrs.Add(ProcessAttribute.Token(Token.Handle));
                    }

                    using (ProcessAttributeList attr_list = ProcessAttributeList.Create(attrs)) {
                        create_info.Data.InitFlags = InitFlags | ProcessCreateInitFlag.WriteOutputOnExit;
                        create_info.Data.ProhibitedImageCharacteristics = ProhibitedImageCharacteristics;
                        create_info.Data.AdditionalFileAccess           = AdditionalFileAccess;

                        using (ObjectAttributes proc_attr = new ObjectAttributes(null, AttributeFlags.None,
                                                                                 SafeKernelObjectHandle.Null, null, ProcessSecurityDescriptor),
                               thread_attr = new ObjectAttributes(null, AttributeFlags.None,
                                                                  SafeKernelObjectHandle.Null, null, ThreadSecurityDescriptor)) {
                            NtStatus status = NtSystemCalls.NtCreateUserProcess(
                                out SafeKernelObjectHandle process_handle, out SafeKernelObjectHandle thread_handle,
                                ProcessDesiredAccess, ThreadDesiredAccess,
                                proc_attr, thread_attr, ProcessFlags,
                                ThreadFlags, process_params.DangerousGetHandle(), create_info, attr_list);

                            if (!status.IsSuccess() && !ReturnOnError)
                            {
                                // Close handles which come from errors
                                switch (create_info.State)
                                {
                                case ProcessCreateState.FailOnSectionCreate:
                                    NtSystemCalls.NtClose(create_info.Data.FileHandle);
                                    break;

                                case ProcessCreateState.FailExeName:
                                    NtSystemCalls.NtClose(create_info.Data.IFEOKey);
                                    break;
                                }

                                status.ToNtException();
                            }

                            if (create_info.State == ProcessCreateState.Success)
                            {
                                return(new CreateUserProcessResult(process_handle, thread_handle,
                                                                   create_info.Data, image_info.Result, client_id.Result, TerminateOnDispose));
                            }
                            else
                            {
                                return(new CreateUserProcessResult(status, create_info.Data, create_info.State));
                            }
                        }
                    }
                }
            }
        }
示例#28
0
        private NtResult <SafeHGlobalBuffer> CreateAbsoluteSecurityDescriptor(bool throw_on_error)
        {
            byte[] dacl       = Dacl?.ToByteArray();
            byte[] sacl       = Sacl?.ToByteArray();
            byte[] owner      = Owner?.Sid.ToArray();
            byte[] group      = Group?.Sid.ToArray();
            int    total_size = GetLength(dacl) + GetLength(sacl) + GetLength(owner) + GetLength(group);

            using (var sd_buffer = new SafeStructureInOutBuffer <SecurityDescriptorStructure>(total_size, true))
            {
                NtStatus status = NtRtl.RtlCreateSecurityDescriptor(sd_buffer, Revision);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                }

                SecurityDescriptorControl control = Control & SecurityDescriptorControl.ValidControlSetMask;
                status = NtRtl.RtlSetControlSecurityDescriptor(sd_buffer, control, control);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                }

                int current_ofs = 0;
                if (Dacl != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, Dacl.NullAcl ? null : dacl, ref current_ofs);
                    status = NtRtl.RtlSetDaclSecurityDescriptor(sd_buffer, true, ptr, Dacl.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                if (Sacl != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, Sacl.NullAcl ? null : sacl, ref current_ofs);
                    status = NtRtl.RtlSetSaclSecurityDescriptor(sd_buffer, true, ptr, Sacl.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                if (Owner != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, owner, ref current_ofs);
                    status = NtRtl.RtlSetOwnerSecurityDescriptor(sd_buffer, ptr, Owner.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                if (Group != null)
                {
                    IntPtr ptr = UpdateBuffer(sd_buffer, group, ref current_ofs);
                    status = NtRtl.RtlSetGroupSecurityDescriptor(sd_buffer, ptr, Group.Defaulted);
                    if (!status.IsSuccess())
                    {
                        return(status.CreateResultFromError <SafeHGlobalBuffer>(throw_on_error));
                    }
                }

                return(status.CreateResult <SafeHGlobalBuffer>(throw_on_error, () => sd_buffer.Detach()));
            }
        }
示例#29
0
        /// <summary>
        /// Parse the policy from the Local Security Authority.
        /// </summary>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The list of Central Access Policies.</returns>
        public static NtResult <CentralAccessPolicy[]> ParseFromLsa(bool throw_on_error)
        {
            NtStatus status = SecurityNativeMethods.LsaGetAppliedCAPIDs(null, out SafeLsaMemoryBuffer capids, out int capid_count);

            if (!status.IsSuccess())
            {
                return(status.CreateResultFromError <CentralAccessPolicy[]>(throw_on_error));
            }
            List <CentralAccessPolicy> ret = new List <CentralAccessPolicy>();

            using (capids) {
                status = SecurityNativeMethods.LsaQueryCAPs(capids.DangerousGetHandle(), capid_count, out SafeLsaMemoryBuffer caps, out uint cap_count);
                if (!status.IsSuccess())
                {
                    return(status.CreateResultFromError <CentralAccessPolicy[]>(throw_on_error));
                }
                caps.Initialize <CENTRAL_ACCESS_POLICY>(cap_count);
                CENTRAL_ACCESS_POLICY[] policies = new CENTRAL_ACCESS_POLICY[cap_count];
                caps.ReadArray(0, policies, 0, policies.Length);
                foreach (var policy in policies)
                {
                    SafeHGlobalBuffer buffer       = new SafeHGlobalBuffer(policy.CAPEs, policy.CAPECount * IntPtr.Size, false);
                    IntPtr[]          rule_entries = new IntPtr[policy.CAPECount];
                    buffer.ReadArray(0, rule_entries, 0, policy.CAPECount);
                    List <CentralAccessRule> rules = new List <CentralAccessRule>();
                    foreach (var ptr in rule_entries)
                    {
                        var entry                     = new SafeStructureInOutBuffer <CENTRAL_ACCESS_POLICY_ENTRY>(ptr, Marshal.SizeOf(typeof(CENTRAL_ACCESS_POLICY_ENTRY)), false);
                        var r                         = entry.Result;
                        SecurityDescriptor sd         = null;
                        SecurityDescriptor staged_sd  = null;
                        string             applies_to = string.Empty;
                        if (r.LengthSD > 0)
                        {
                            var result = SecurityDescriptor.Parse(r.SD, throw_on_error);
                            if (!result.IsSuccess)
                            {
                                return(result.Cast <CentralAccessPolicy[]>());
                            }
                            sd = result.Result;
                        }
                        if (r.LengthStagedSD > 0)
                        {
                            var result = SecurityDescriptor.Parse(r.StagedSD, throw_on_error);
                            if (!result.IsSuccess)
                            {
                                return(result.Cast <CentralAccessPolicy[]>());
                            }
                            staged_sd = result.Result;
                        }
                        if (r.LengthAppliesTo > 0)
                        {
                            byte[] condition = new byte[r.LengthAppliesTo];
                            Marshal.Copy(r.AppliesTo, condition, 0, r.LengthAppliesTo);
                            var result = NtSecurity.ConditionalAceToString(condition, throw_on_error);
                            if (!result.IsSuccess)
                            {
                                return(result.Cast <CentralAccessPolicy[]>());
                            }
                            applies_to = result.Result;
                        }

                        rules.Add(new CentralAccessRule(r.Name.ToString(), r.Description.ToString(),
                                                        sd, staged_sd, applies_to, r.ChangeId.ToString(), r.Flags));
                    }
                    var capid = Sid.Parse(policy.CAPID, throw_on_error);
                    if (!capid.IsSuccess)
                    {
                        return(capid.Cast <CentralAccessPolicy[]>());
                    }
                    ret.Add(new CentralAccessPolicy(capid.Result, policy.Flags, policy.Name.ToString(),
                                                    policy.Description.ToString(), policy.ChangeId.ToString(), rules));
                }
            }
            return(ret.ToArray().CreateResult());
        }