private static int GetTypeSize() { using (var type_info = new SafeStructureInOutBuffer <ObjectAllTypesInformation>()) { Dictionary <string, NtType> ret = new Dictionary <string, NtType>(StringComparer.OrdinalIgnoreCase); NtStatus status = NtSystemCalls.NtQueryObject(SafeKernelObjectHandle.Null, ObjectInformationClass.ObjectTypesInformation, type_info, type_info.Length, out int return_length); if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH) { status.ToNtException(); } return(return_length); } }
/// <summary> /// Query a variable buffer from the object. /// </summary> /// <typeparam name="T">The type of structure to return.</typeparam> /// <param name="info_class">The information class to query.</param> /// <param name="default_value">A default value for the query.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The result of the query.</returns> /// <exception cref="NtException">Thrown on error.</exception> public virtual NtResult <SafeStructureInOutBuffer <T> > QueryBuffer <T>(Q info_class, T default_value, bool throw_on_error) where T : new() { NtStatus status; int return_length; // First try base size before trying to reallocate. using (var buffer = default_value.ToBuffer()) { status = QueryInformation(info_class, buffer, out return_length); if (status.IsSuccess()) { return(status.CreateResult(false, () => buffer.Detach())); } } if (!IsInvalidBufferStatus(status)) { return(status.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error)); } // If the function returned a length then trust it. if (return_length > 0 && GetTrustReturnLength(info_class)) { using (var buffer = new SafeStructureInOutBuffer <T>(default_value, return_length, false)) { return(QueryInformation(info_class, buffer, out return_length).CreateResult(throw_on_error, () => buffer.Detach())); } } // Function length can't be trusted, we'll need to brute force it. return_length = GetSmallestPower2(Marshal.SizeOf(typeof(T))); int max_length = GetMaximumBruteForceLength(info_class); while (return_length < max_length) { using (var buffer = new SafeStructureInOutBuffer <T>(default_value, return_length, false)) { status = QueryInformation(info_class, buffer, out int dummy_length); if (status.IsSuccess()) { return(status.CreateResult(throw_on_error, () => buffer.Detach())); } else if (!IsInvalidBufferStatus(status)) { return(status.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error)); } return_length *= 2; } } return(NtStatus.STATUS_BUFFER_TOO_SMALL.CreateResultFromError <SafeStructureInOutBuffer <T> >(throw_on_error)); }
internal FileSystemVolumeInformation(SafeStructureInOutBuffer <FileFsAttributeInformation> attr_info, SafeStructureInOutBuffer <FileFsVolumeInformation> vol_info) { var attr_info_res = attr_info.Result; var vol_info_res = vol_info.Result; Attributes = attr_info_res.FileSystemAttributes; MaximumComponentLength = attr_info_res.MaximumComponentNameLength; Name = attr_info.Data.ReadUnicodeString(attr_info_res.FileSystemNameLength / 2); CreationTime = DateTime.FromFileTime(vol_info_res.VolumeCreationTime.QuadPart); SerialNumber = vol_info_res.VolumeSerialNumber; SupportsObjects = vol_info_res.SupportsObjects; Label = vol_info.Data.ReadUnicodeString(vol_info_res.VolumeLabelLength / 2); }
/// <summary> /// Get a notification synchronously. /// </summary> /// <param name="timeout">Optional timeout for getting the notification.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The transaction notification.</returns> public NtResult <TransactionNotification> GetNotification(NtWaitTimeout timeout, bool throw_on_error) { NtStatus status = NtSystemCalls.NtGetNotificationResourceManager(Handle, SafeHGlobalBuffer.Null, 0, timeout.ToLargeInteger(), out int return_length, 0, IntPtr.Zero); if (status != NtStatus.STATUS_BUFFER_TOO_SMALL) { return(status.CreateResultFromError <TransactionNotification>(throw_on_error)); } using (var buffer = new SafeStructureInOutBuffer <TransactionNotificationData>(return_length, false)) { return(NtSystemCalls.NtGetNotificationResourceManager(Handle, buffer, buffer.Length, timeout.ToLargeInteger(), out return_length, 0, IntPtr.Zero) .CreateResult(throw_on_error, () => new TransactionNotification(buffer))); } }
/// <summary> /// Get process image file path /// </summary> /// <param name="native">True to return the native image path, false for a Win32 style path</param> /// <returns>The process image file path</returns> public string GetImageFilePath(bool native) { ProcessInfoClass info_class = native ? ProcessInfoClass.ProcessImageFileName : ProcessInfoClass.ProcessImageFileNameWin32; int return_length = 0; NtStatus status = NtSystemCalls.NtQueryInformationProcess(Handle, info_class, SafeHGlobalBuffer.Null, 0, out return_length); if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH) { status.ToNtException(); } using (SafeStructureInOutBuffer <UnicodeStringOut> buf = new SafeStructureInOutBuffer <UnicodeStringOut>(return_length, false)) { NtSystemCalls.NtQueryInformationProcess(Handle, info_class, buf, buf.Length, out return_length).ToNtException(); return(buf.Result.ToString()); } }
private static Dictionary <string, NtType> LoadTypes() { var type_factories = NtTypeFactory.GetAssemblyNtTypeFactories(Assembly.GetExecutingAssembly()); SafeStructureInOutBuffer <ObjectAllTypesInformation> type_info = new SafeStructureInOutBuffer <ObjectAllTypesInformation>(); try { Dictionary <string, NtType> ret = new Dictionary <string, NtType>(StringComparer.OrdinalIgnoreCase); int return_length; NtStatus status = NtSystemCalls.NtQueryObject(SafeKernelObjectHandle.Null, ObjectInformationClass.ObjectAllInformation, type_info.DangerousGetHandle(), type_info.Length, out return_length); if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH) { status.ToNtException(); } type_info.Close(); type_info = null; type_info = new SafeStructureInOutBuffer <ObjectAllTypesInformation>(return_length, false); int alignment = IntPtr.Size - 1; NtSystemCalls.NtQueryObject(SafeKernelObjectHandle.Null, ObjectInformationClass.ObjectAllInformation, type_info.DangerousGetHandle(), type_info.Length, out return_length).ToNtException(); ObjectAllTypesInformation result = type_info.Result; IntPtr curr_typeinfo = type_info.DangerousGetHandle() + IntPtr.Size; for (int count = 0; count < result.NumberOfTypes; ++count) { ObjectTypeInformation info = (ObjectTypeInformation)Marshal.PtrToStructure(curr_typeinfo, typeof(ObjectTypeInformation)); string name = info.Name.ToString(); NtTypeFactory factory = type_factories.ContainsKey(name) ? type_factories[name] : _generic_factory; NtType ti = new NtType(count + 2, info, factory); ret[ti.Name] = ti; int offset = (info.Name.MaximumLength + alignment) & ~alignment; curr_typeinfo = info.Name.Buffer + offset; } return(ret); } finally { if (type_info != null) { type_info.Close(); } } }
private string TryGetName() { using (SafeStructureInOutBuffer <FileNameInformation> buffer = new SafeStructureInOutBuffer <FileNameInformation>(32 * 1024, true)) { try { IoStatus status = new IoStatus(); NtSystemCalls.NtQueryInformationFile(Handle, status, buffer, buffer.Length, FileInformationClass.FileNameInformation).ToNtException(); char[] result = new char[buffer.Result.NameLength / 2]; buffer.Data.ReadArray(0, result, 0, result.Length); return(new string(result)); } catch (NtException) { return(String.Empty); } } }
private SafeHGlobalBuffer CreateAbsoluteSecurityDescriptor() { SafeStructureInOutBuffer <SecurityDescriptorStructure> sd_buffer = null; try { 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); sd_buffer = new SafeStructureInOutBuffer <SecurityDescriptorStructure>(total_size, true); NtRtl.RtlCreateSecurityDescriptor(sd_buffer, Revision).ToNtException(); SecurityDescriptorControl control = Control & SecurityDescriptorControl.ValidControlSetMask; NtRtl.RtlSetControlSecurityDescriptor(sd_buffer, control, control).ToNtException(); int current_ofs = 0; if (Dacl != null) { IntPtr ptr = UpdateBuffer(sd_buffer, Dacl.NullAcl ? null : dacl, ref current_ofs); NtRtl.RtlSetDaclSecurityDescriptor(sd_buffer, true, ptr, Dacl.Defaulted).ToNtException(); } if (Sacl != null) { IntPtr ptr = UpdateBuffer(sd_buffer, Sacl.NullAcl ? null : sacl, ref current_ofs); NtRtl.RtlSetSaclSecurityDescriptor(sd_buffer, true, ptr, Sacl.Defaulted).ToNtException(); } if (Owner != null) { IntPtr ptr = UpdateBuffer(sd_buffer, owner, ref current_ofs); NtRtl.RtlSetOwnerSecurityDescriptor(sd_buffer, ptr, Owner.Defaulted); } if (Group != null) { IntPtr ptr = UpdateBuffer(sd_buffer, group, ref current_ofs); NtRtl.RtlSetGroupSecurityDescriptor(sd_buffer, ptr, Group.Defaulted); } return(Interlocked.Exchange(ref sd_buffer, null)); } finally { sd_buffer?.Close(); } }
/// <summary> /// For the current process /// </summary> /// <param name="process_create_flags">Process create flags.</param> /// <param name="thread_create_flags">Thread create flags.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The new forked process result</returns> public static NtResult <CreateUserProcessResult> Fork(ProcessCreateFlags process_create_flags, ThreadCreateFlags thread_create_flags, bool throw_on_error) { using (var attrs = new DisposableList <ProcessAttribute>()) { ProcessCreateInfo create_info = new ProcessCreateInfo(); SafeStructureInOutBuffer <ClientId> client_id = new SafeStructureInOutBuffer <ClientId>(); attrs.Add(ProcessAttribute.ClientId(client_id)); ProcessAttributeList attr_list = new ProcessAttributeList(attrs); return(NtSystemCalls.NtCreateUserProcess( out SafeKernelObjectHandle process_handle, out SafeKernelObjectHandle thread_handle, ProcessAccessRights.MaximumAllowed, ThreadAccessRights.MaximumAllowed, null, null, process_create_flags | ProcessCreateFlags.InheritFromParent, thread_create_flags, IntPtr.Zero, create_info, attr_list).CreateResult(throw_on_error, () => new CreateUserProcessResult(process_handle, thread_handle, create_info.Data, new SectionImageInformation(), client_id.Result, false))); } }
/// <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; } MemoryRegionInformation region_info = new MemoryRegionInformation(); using (var buffer = new SafeStructureInOutBuffer <MemoryRegionInformation>()) { NtStatus status = NtSystemCalls.NtQueryVirtualMemory(process, new IntPtr(base_address), MemoryInformationClass.MemoryRegionInformationEx, buffer, buffer.LengthIntPtr, out IntPtr ret_length); if (status.IsSuccess()) { region_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, region_info).CreateResult()); }
/// <summary> /// Query the directory for a list of entries. /// </summary> /// <returns>The list of entries.</returns> /// <exception cref="NtException">Thrown on error</exception> public IEnumerable <ObjectDirectoryInformation> Query() { string base_path = FullPath.TrimEnd('\\'); using (SafeStructureInOutBuffer <OBJECT_DIRECTORY_INFORMATION> buffer = new SafeStructureInOutBuffer <OBJECT_DIRECTORY_INFORMATION>(2048, true)) { NtStatus status; int context = 0; int return_length = 0; while ((status = NtSystemCalls.NtQueryDirectoryObject(Handle, buffer, buffer.Length, false, true, ref context, out return_length)) == NtStatus.STATUS_MORE_ENTRIES) { buffer.Resize(buffer.Length * 2); } if (status == NtStatus.STATUS_NO_MORE_ENTRIES) { yield break; } status.ToNtException(); IntPtr current = buffer.DangerousGetHandle(); string name = String.Empty; while (true) { OBJECT_DIRECTORY_INFORMATION dir_info = (OBJECT_DIRECTORY_INFORMATION)Marshal.PtrToStructure(current, typeof(OBJECT_DIRECTORY_INFORMATION)); name = dir_info.Name.ToString(); if (name.Length == 0) { break; } yield return(new ObjectDirectoryInformation(this, base_path, dir_info)); current += Marshal.SizeOf(dir_info); } } }
private SafeStructureInOutBuffer <T> Query <T>(ProcessInfoClass info_class) where T : new() { int return_length = 0; NtStatus status = NtSystemCalls.NtQueryInformationProcess(Handle, info_class, SafeHGlobalBuffer.Null, 0, out return_length); if (status != NtStatus.STATUS_INFO_LENGTH_MISMATCH && status != NtStatus.STATUS_BUFFER_TOO_SMALL) { throw new NtException(status); } SafeStructureInOutBuffer <T> buffer = new SafeStructureInOutBuffer <T>(return_length, false); try { NtSystemCalls.NtQueryInformationProcess(Handle, info_class, buffer, buffer.Length, out return_length).ToNtException(); return(buffer); } catch { buffer.Close(); throw; } }
/// <summary> /// Query memory information for a process. /// </summary> /// <param name="process">The process to query.</param> /// <param name="base_address">The base address.</param> /// <returns>The memory information for the region.</returns> /// <exception cref="NtException">Thrown on error.</exception> public static MemoryInformation QueryMemoryInformation(SafeKernelObjectHandle process, long base_address) { MemoryBasicInformation basic_info = new MemoryBasicInformation(); string mapped_image_path = String.Empty; using (var buffer = new SafeStructureInOutBuffer <MemoryBasicInformation>()) { NtSystemCalls.NtQueryVirtualMemory(process, new IntPtr(base_address), MemoryInformationClass.MemoryBasicInformation, buffer, buffer.LengthIntPtr, out IntPtr ret_length).ToNtException(); 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)); }
private SafeStructureInOutBuffer <T> QueryKey <T>(KeyInformationClass info_class) where T : new() { int return_length; NtStatus status = NtSystemCalls.NtQueryKey(Handle, info_class, SafeHGlobalBuffer.Null, 0, out return_length); if (status != NtStatus.STATUS_BUFFER_OVERFLOW && status != NtStatus.STATUS_INFO_LENGTH_MISMATCH && status != NtStatus.STATUS_BUFFER_TOO_SMALL) { status.ToNtException(); } SafeStructureInOutBuffer <T> buffer = new SafeStructureInOutBuffer <T>(return_length, false); try { NtSystemCalls.NtQueryKey(Handle, info_class, buffer, buffer.Length, out return_length).ToNtException(); return(Interlocked.Exchange(ref buffer, null)); } finally { if (buffer != null) { buffer.Close(); } } }
/// <summary> /// Query a fixed structure from the object. /// </summary> /// <typeparam name="T">The type of structure to return.</typeparam> /// <param name="info_class">The information class to query.</param> /// <param name="default_value">A default value for the query.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The result of the query.</returns> /// <exception cref="NtException">Thrown on error.</exception> public virtual NtResult <T> Query <T>(Q info_class, T default_value, bool throw_on_error) where T : new() { using (var buffer = new SafeStructureInOutBuffer <T>(default_value)) { return(QueryInformation(info_class, buffer, out int return_length).CreateResult(throw_on_error, () => buffer.Result)); } }
/// <summary> /// Convert security descriptor to a byte array /// </summary> /// <returns>The binary security descriptor</returns> public byte[] ToByteArray() { SafeStructureInOutBuffer <SecurityDescriptorStructure> sd_buffer = null; SafeHGlobalBuffer dacl_buffer = null; SafeHGlobalBuffer sacl_buffer = null; SafeSidBufferHandle owner_buffer = null; SafeSidBufferHandle group_buffer = null; try { sd_buffer = new SafeStructureInOutBuffer <SecurityDescriptorStructure>(); NtRtl.RtlCreateSecurityDescriptor(sd_buffer, Revision).ToNtException(); SecurityDescriptorControl control = Control & SecurityDescriptorControl.ValidControlSetMask; NtRtl.RtlSetControlSecurityDescriptor(sd_buffer, control, control).ToNtException(); if (Dacl != null) { if (!Dacl.NullAcl) { dacl_buffer = new SafeHGlobalBuffer(Dacl.ToByteArray()); } else { dacl_buffer = new SafeHGlobalBuffer(IntPtr.Zero, 0, false); } NtRtl.RtlSetDaclSecurityDescriptor(sd_buffer, true, dacl_buffer.DangerousGetHandle(), Dacl.Defaulted).ToNtException(); } if (Sacl != null) { if (!Sacl.NullAcl) { sacl_buffer = new SafeHGlobalBuffer(Sacl.ToByteArray()); } else { sacl_buffer = new SafeHGlobalBuffer(IntPtr.Zero, 0, false); } NtRtl.RtlSetSaclSecurityDescriptor(sd_buffer, true, sacl_buffer.DangerousGetHandle(), Sacl.Defaulted).ToNtException(); } if (Owner != null) { owner_buffer = Owner.Sid.ToSafeBuffer(); NtRtl.RtlSetOwnerSecurityDescriptor(sd_buffer, owner_buffer.DangerousGetHandle(), Owner.Defaulted); } if (Group != null) { group_buffer = Group.Sid.ToSafeBuffer(); NtRtl.RtlSetGroupSecurityDescriptor(sd_buffer, group_buffer.DangerousGetHandle(), Group.Defaulted); } int total_length = 0; NtStatus status = NtRtl.RtlAbsoluteToSelfRelativeSD(sd_buffer, new SafeHGlobalBuffer(IntPtr.Zero, 0, false), ref total_length); if (status != NtStatus.STATUS_BUFFER_TOO_SMALL) { status.ToNtException(); } using (SafeHGlobalBuffer relative_sd = new SafeHGlobalBuffer(total_length)) { NtRtl.RtlAbsoluteToSelfRelativeSD(sd_buffer, relative_sd, ref total_length).ToNtException(); return(relative_sd.ToArray()); } } finally { sd_buffer?.Close(); dacl_buffer?.Close(); sacl_buffer?.Close(); owner_buffer?.Close(); group_buffer?.Close(); } }
public static ProcessAttribute ClientId(SafeStructureInOutBuffer <ClientId> client_id) { return(new ProcessAttribute(ProcessAttributeNum.ClientId, true, false, false, client_id)); }
public static ProcessAttribute ImageInfo(SafeStructureInOutBuffer <SectionImageInformation> image_information) { return(new ProcessAttribute(ProcessAttributeNum.ImageInfo, false, false, false, image_information)); }
/// <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(); } } }
/// <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)); } } } } } }
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())); } }