/// <summary> /// Create a new AppContainerProfile. /// </summary> /// <param name="appcontainer_name">The name of the AppContainer.</param> /// <param name="display_name">A display name.</param> /// <param name="description">An optional description.</param> /// <param name="capabilities">An optional list of capability SIDs.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The created AppContainer profile.</returns> /// <remarks>If the profile already exists then it'll be opened instead.</remarks> public static NtResult <AppContainerProfile> Create( string appcontainer_name, string display_name, string description, IEnumerable <Sid> capabilities, bool throw_on_error) { using (var resources = new DisposableList()) { var caps = resources.CreateSidAndAttributes(capabilities); NtStatus status = Win32NativeMethods.CreateAppContainerProfile(appcontainer_name, display_name, description, caps.Length > 0 ? caps : null, caps.Length, out SafeSidBufferHandle sid); if (status == NtObjectUtils.MapDosErrorToStatus(Win32Error.ERROR_ALREADY_EXISTS)) { return(new AppContainerProfile(appcontainer_name).CreateResult()); } resources.AddResource(sid); return(status.CreateResult(throw_on_error, () => { using (sid) { return new AppContainerProfile(appcontainer_name, sid.ToSid(), capabilities, display_name, description); } })); } }
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> /// Determine if two addresses are the same mapped file. /// </summary> /// <param name="address_1">The first address.</param> /// <param name="address_2">The second address.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>True if the mapped memory is the same file.</returns> public static NtResult <bool> AreMappedFilesTheSame(long address_1, long address_2, bool throw_on_error) { NtStatus status = NtSystemCalls.NtAreMappedFilesTheSame(new IntPtr(address_1), new IntPtr(address_2)); if (status == NtStatus.STATUS_NOT_SAME_DEVICE) { return(false.CreateResult()); } return(status.CreateResult(throw_on_error, () => true)); }
/// <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); } } }
private static NtResult <List <Sid> > GetSids(SafeLsaHandle policy, string name, bool throw_on_error) { if (name is null) { throw new ArgumentNullException(nameof(name)); } NtStatus status = SecurityNativeMethods.LsaEnumerateAccountsWithUserRight(policy, new UnicodeString(name), out SafeLsaMemoryBuffer buffer, out int count); if (status == NtStatus.STATUS_NO_MORE_ENTRIES) { return(new List <Sid>().CreateResult()); } return(status.CreateResult(throw_on_error, () => ParseSids(buffer, count))); }
/// <summary> /// Enumerate accounts with a user right. /// </summary> /// <param name="user_right">The name of the user right.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The list of SIDs with the user right.</returns> public NtResult <IReadOnlyList <Sid> > EnumerateAccountsWithUserRight(string user_right, bool throw_on_error) { if (user_right is null) { throw new ArgumentNullException(nameof(user_right)); } NtStatus status = SecurityNativeMethods.LsaEnumerateAccountsWithUserRight(Handle, new UnicodeString(user_right), out SafeLsaMemoryBuffer buffer, out int count); if (status == NtStatus.STATUS_NO_MORE_ENTRIES) { return(new List <Sid>().AsReadOnly().CreateResult <IReadOnlyList <Sid> >()); } return(status.CreateResult(throw_on_error, () => ParseSids(buffer, count))); }
/// <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); } } } }
/// <summary> /// Get security descriptor as a byte array /// </summary> /// <param name="security_information">What parts of the security descriptor to retrieve</param> /// <param name="throw_on_error">True to throw on error.</param> /// <return>The NT status result and security descriptor.</return> public NtResult <byte[]> GetSecurityDescriptorBytes(SecurityInformation security_information, bool throw_on_error) { // Just do a check here, no point checking if ReadControl not available. if (!IsAccessMaskGranted(GenericAccessRights.ReadControl)) { return(NtStatus.STATUS_ACCESS_DENIED.CreateResultFromError <byte[]>(throw_on_error)); } NtStatus status = NtSystemCalls.NtQuerySecurityObject(Handle, security_information, null, 0, out int return_length); if (status != NtStatus.STATUS_BUFFER_TOO_SMALL) { return(status.CreateResult(throw_on_error, () => new byte[0])); } byte[] buffer = new byte[return_length]; return(NtSystemCalls.NtQuerySecurityObject(Handle, security_information, buffer, buffer.Length, out return_length).CreateResult(throw_on_error, () => buffer)); }
/// <summary> /// Query state data for the WNF object. /// </summary> /// <param name="type_id">Optional Type ID.</param> /// <param name="explicit_scope">Optional explicit scope.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The state data.</returns> public NtResult <WnfStateData> QueryStateData(WnfTypeId type_id, IntPtr explicit_scope, bool throw_on_error) { int tries = 10; int size = 4096; while (tries-- > 0) { using (var buffer = new SafeHGlobalBuffer(size)) { NtStatus status = NtSystemCalls.NtQueryWnfStateData(StateName, type_id, explicit_scope, out int changestamp, buffer, ref size); if (status == NtStatus.STATUS_BUFFER_TOO_SMALL) { continue; } return(status.CreateResult(throw_on_error, () => new WnfStateData(buffer.ReadBytes(size), changestamp))); } } return(NtStatus.STATUS_BUFFER_TOO_SMALL.CreateResultFromError <WnfStateData>(throw_on_error)); }
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())); } }