/// <summary>
        /// Method to create an object from a set of object attributes.
        /// </summary>
        /// <param name="obj_attributes">The object attributes to create/open from.</param>
        /// <returns>The newly created object.</returns>
        protected override object CreateObject(ObjectAttributes obj_attributes)
        {
            string key_path = Win32Path ? NtKeyUtils.Win32KeyNameToNt(KeyPath) : KeyPath;

            using (ObjectAttributes name = new ObjectAttributes(key_path, AttributeFlags.CaseInsensitive))
            {
                if ((LoadFlags & LoadKeyFlags.AppKey) == 0)
                {
                    using (NtToken token = NtToken.OpenProcessToken())
                    {
                        TokenPrivilege priv = token.GetPrivilege(TokenPrivilegeValue.SeRestorePrivilege);
                        if (priv == null || (priv.Attributes & PrivilegeAttributes.Enabled) == 0)
                        {
                            WriteWarning("Loading a non-app hive should require SeRestorePrivilege");
                        }
                    }
                }
                else
                {
                    if (!KeyPath.StartsWith(@"\Registry\A\", System.StringComparison.OrdinalIgnoreCase))
                    {
                        WriteWarning(@"Loading app hive outside of \Registry\A\ will fail on an up to date system.");
                    }
                }

                return(NtKey.LoadKey(name, obj_attributes, LoadFlags, Access));
            }
        }
Beispiel #2
0
 private NtResult <NtKey> Open(string path, KeyAccessRights desired_access, bool throw_on_error)
 {
     using (var obja = new ObjectAttributes(path, AttributeFlags.OpenLink | AttributeFlags.CaseInsensitive, _key))
     {
         return(NtKey.Open(obja, desired_access, _open_for_backup ? KeyCreateOptions.BackupRestore : KeyCreateOptions.NonVolatile, throw_on_error));
     }
 }
        private static Dictionary <Guid, EventTraceProvider> GetProvidersInternal()
        {
            int retry_count   = 10;
            int buffer_length = 1024;
            Dictionary <Guid, EventTraceProvider> providers = new Dictionary <Guid, EventTraceProvider>();

            while (retry_count-- > 0)
            {
                using (var buffer = new SafeStructureInOutBuffer <PROVIDER_ENUMERATION_INFO>(buffer_length, false))
                {
                    Win32Error error = Win32NativeMethods.TdhEnumerateProviders(buffer, ref buffer_length);
                    if (error == Win32Error.ERROR_INSUFFICIENT_BUFFER)
                    {
                        continue;
                    }
                    if (error != Win32Error.SUCCESS)
                    {
                        error.ToNtException();
                    }
                    var result = buffer.Result;
                    var data   = buffer.Data;
                    TRACE_PROVIDER_INFO[] infos = new TRACE_PROVIDER_INFO[result.NumberOfProviders];
                    buffer.Data.ReadArray(0, infos, 0, infos.Length);
                    foreach (var info in infos)
                    {
                        if (!providers.ContainsKey(info.ProviderGuid))
                        {
                            providers.Add(info.ProviderGuid,
                                          new EventTraceProvider(info.ProviderGuid,
                                                                 buffer.ReadNulTerminatedUnicodeString(info.ProviderNameOffset),
                                                                 info.SchemaSource == 0));
                        }
                    }
                    break;
                }
            }
            foreach (var guid in GetTraceGuids())
            {
                if (!providers.ContainsKey(guid))
                {
                    providers.Add(guid, new EventTraceProvider(guid));
                }
            }
            using (var key = NtKey.Open(@"\REGISTRY\MACHINE\SYSTEM\CurrentControlSet\Control\WMI\Security",
                                        null, KeyAccessRights.QueryValue, KeyCreateOptions.NonVolatile, false))
            {
                if (key.IsSuccess)
                {
                    foreach (var value in key.Result.QueryValues())
                    {
                        if (Guid.TryParse(value.Name, out Guid id) && !providers.ContainsKey(id))
                        {
                            providers.Add(id, new EventTraceProvider(id,
                                                                     SecurityDescriptor.Parse(value.Data, false).GetResultOrDefault()));
                        }
                    }
                }
            }
            return(providers);
        }
Beispiel #4
0
        private static NtResult <CentralAccessPolicy[]> ReadPolicies(NtKey base_key, Dictionary <int, CentralAccessRule> rules, bool throw_on_error)
        {
            List <CentralAccessPolicy> policies = new List <CentralAccessPolicy>();

            using (var key = base_key.Open("CAPs", KeyAccessRights.EnumerateSubKeys, throw_on_error)) {
                if (!key.IsSuccess)
                {
                    return(key.Cast <CentralAccessPolicy[]>());
                }
                using (var list = key.Result.QueryAccessibleKeys(KeyAccessRights.QueryValue).ToDisposableList()) {
                    foreach (var subkey in list)
                    {
                        if (!int.TryParse(subkey.Name, out int index))
                        {
                            continue;
                        }
                        var policy = FromRegistry(subkey, rules, throw_on_error);
                        if (!policy.IsSuccess)
                        {
                            return(policy.Cast <CentralAccessPolicy[]>());
                        }
                        policies.Add(policy.Result);
                    }
                }
            }
            return(policies.ToArray().CreateResult());
        }
Beispiel #5
0
        static void DumpKey(NtKey key)
        {
            string key_name = key.FullPath;

            if (_walked.Contains(key_name))
            {
                return;
            }

            _walked.Add(key_name);

            try
            {
                CheckAccess(key);

                if (_recursive && key.IsAccessGranted(KeyAccessRights.EnumerateSubKeys))
                {
                    using (var keys = key.QueryAccessibleKeys(KeyAccessRights.MaximumAllowed))
                    {
                        foreach (NtKey subkey in keys)
                        {
                            DumpKey(subkey);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("Error dumping key {0} {1}", key.FullPath, ex.Message);
            }
        }
Beispiel #6
0
        private static NtResult <Dictionary <int, CentralAccessRule> > ReadRules(NtKey base_key, bool throw_on_error)
        {
            Dictionary <int, CentralAccessRule> rules = new Dictionary <int, CentralAccessRule>();

            using (var key = base_key.Open("CAPEs", KeyAccessRights.EnumerateSubKeys, throw_on_error)) {
                if (!key.IsSuccess)
                {
                    return(key.Cast <Dictionary <int, CentralAccessRule> >());
                }
                using (var list = key.Result.QueryAccessibleKeys(KeyAccessRights.QueryValue).ToDisposableList()) {
                    foreach (var subkey in list)
                    {
                        if (!int.TryParse(subkey.Name, out int index))
                        {
                            continue;
                        }
                        var rule = CentralAccessRule.FromRegistry(subkey, throw_on_error);
                        if (!rule.IsSuccess)
                        {
                            return(rule.Cast <Dictionary <int, CentralAccessRule> >());
                        }
                        rules[index] = rule.Result;
                    }
                }
            }
            return(rules.CreateResult());
        }
Beispiel #7
0
 /// <summary>
 /// Method to create an object from a set of object attributes.
 /// </summary>
 /// <param name="obj_attributes">The object attributes to create/open from.</param>
 /// <returns>The newly created object.</returns>
 protected override object CreateObject(ObjectAttributes obj_attributes)
 {
     using (NtKey key = (NtKey)base.CreateObject(obj_attributes))
     {
         key.SetSymbolicLinkTarget(Win32Path ? NtKeyUtils.Win32KeyNameToNt(Target) : Target);
     }
     return(null);
 }
Beispiel #8
0
 private protected override void RunAccessCheckPath(IEnumerable <TokenEntry> tokens, string path)
 {
     using (var result = OpenKey(path, null, false, _open_for_backup))
     {
         NtKey key = result.GetResultOrThrow();
         DumpKey(tokens, result.Result.NtType.MapGenericRights(Access), _open_for_backup, key, GetMaxDepth());
     }
 }
Beispiel #9
0
 private protected override void PopulateKeyData(NtKey key)
 {
     base.PopulateKeyData(key);
     if (key.IsAccessGranted(KeyAccessRights.QueryValue))
     {
         _values = new List <NtKeyValue>(key.QueryValues());
     }
 }
Beispiel #10
0
 /// <summary>
 /// Method to create an object from a set of object attributes.
 /// </summary>
 /// <param name="obj_attributes">The object attributes to create/open from.</param>
 /// <returns>The newly created object.</returns>
 protected override object CreateObject(ObjectAttributes obj_attributes)
 {
     using (NtKey key = (NtKey)base.CreateObject(obj_attributes))
     {
         string target = key.GetSymbolicLinkTarget();
         return(FormatWin32Path ? NtKeyUtils.NtKeyNameToWin32(target) : target);
     }
 }
Beispiel #11
0
        static NtKey OpenKey(string name)
        {
            if (!name.StartsWith(@"\"))
            {
                name = MapKeyName(name);
            }

            return(NtKey.Open(name, null, KeyAccessRights.MaximumAllowed));
        }
 /// <summary>
 /// Try and open the directory entry and return an actual NtObject handle.
 /// </summary>
 /// <param name="throw_on_error">True to throw on error.</param>
 /// <returns>The object opened.</returns>
 /// <exception cref="System.ArgumentException">Thrown if invalid typename.</exception>
 public override NtResult <NtObject> ToObject(bool throw_on_error)
 {
     using (var obja = new ObjectAttributes(RelativePath, AttributeFlags.OpenLink | AttributeFlags.CaseInsensitive, _root))
     {
         return(NtKey.Open(obja, KeyAccessRights.MaximumAllowed,
                           _open_for_backup ? KeyCreateOptions.BackupRestore : KeyCreateOptions.NonVolatile,
                           throw_on_error).Cast <NtObject>());
     }
 }
Beispiel #13
0
        static void Main(string[] args)
        {
            bool show_help = false;

            int pid = Process.GetCurrentProcess().Id;

            try
            {
                PrintDeprecationWarning();

                OptionSet opts = new OptionSet()
                {
                    { "r", "Recursive tree directory listing",
                      v => _recursive = v != null },
                    { "sddl", "Print full SDDL security descriptors", v => _print_sddl = v != null },
                    { "p|pid=", "Specify a PID of a process to impersonate when checking", v => pid = int.Parse(v.Trim()) },
                    { "w", "Show only write permissions granted", v => _show_write_only = v != null },
                    { "k=", String.Format("Filter on a specific right [{0}]",
                                          String.Join(",", Enum.GetNames(typeof(KeyAccessRights)))), v => _key_rights |= ParseRight(v, typeof(KeyAccessRights)) },
                    { "x=", "Specify a base path to exclude from recursive search", v => _walked.Add(v.ToLower()) },
                    { "g", "Map access mask to generic rights.", v => _map_to_generic = v != null },
                    { "h|help", "show this message and exit", v => show_help = v != null },
                };

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

                if (show_help || (paths.Count == 0))
                {
                    ShowHelp(opts);
                }
                else
                {
                    using (NtToken token = NtToken.OpenProcessToken(pid))
                    {
                        foreach (string path in paths)
                        {
                            try
                            {
                                using (NtKey key = OpenKey(path))
                                {
                                    DumpKey(token, key);
                                }
                            }
                            catch (NtException ex)
                            {
                                Console.Error.WriteLine("Error opening key: {0} - {1}", path, ex.Message);
                            }
                        }
                    }
                }
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
            }
        }
 private protected override void PopulateKeyData(NtKey key)
 {
     base.PopulateKeyData(key);
     if (key.IsAccessGranted(KeyAccessRights.QueryValue))
     {
         _values = new List <NtKeyValue>(key.QueryValues());
     }
     _control_flags        = key.ControlFlags;
     _virtualization_flags = key.VirtualizationFlags;
 }
Beispiel #15
0
        /// <summary>
        /// Parse the policy from the registry.
        /// </summary>
        /// <param name="key">The base key for the registry policy.</param>
        /// <param name="throw_on_error">True to throw on error.</param>
        /// <returns>The list of Central Access Policies.</returns>
        public static NtResult <CentralAccessPolicy[]> ParseFromRegistry(NtKey key, bool throw_on_error)
        {
            var rules = ReadRules(key, throw_on_error);

            if (!rules.IsSuccess)
            {
                return(rules.Cast <CentralAccessPolicy[]>());
            }
            return(ReadPolicies(key, rules.Result, throw_on_error));
        }
Beispiel #16
0
 /// <summary>
 /// Parse the policy from the registry.
 /// </summary>
 /// <param name="throw_on_error">True to throw on error.</param>
 /// <returns>The list of Central Access Policies.</returns>
 public static NtResult <CentralAccessPolicy[]> ParseFromRegistry(bool throw_on_error)
 {
     using (var key = NtKey.Open(POLICY_KEY,
                                 null, KeyAccessRights.EnumerateSubKeys, KeyCreateOptions.NonVolatile, throw_on_error)) {
         if (!key.IsSuccess)
         {
             return(key.Cast <CentralAccessPolicy[]>());
         }
         return(ParseFromRegistry(key.Result, throw_on_error));
     }
 }
Beispiel #17
0
        private void CheckAccess(TokenEntry token, NtKey key, AccessMask access_rights, SecurityDescriptor sd)
        {
            NtType     type           = key.NtType;
            AccessMask granted_access = NtSecurity.GetMaximumAccess(sd, token.Token, type.GenericMapping);

            if (IsAccessGranted(granted_access, access_rights))
            {
                WriteAccessCheckResult(FormatWin32Path ? key.Win32Path : key.FullPath, type.Name, granted_access, type.GenericMapping,
                                       sd, typeof(KeyAccessRights), true, token.Information);
            }
        }
 /// <summary>
 /// Method to create an object from a set of object attributes.
 /// </summary>
 /// <param name="obj_attributes">The object attributes to create/open from.</param>
 /// <returns>The newly created object.</returns>
 protected override object CreateObject(ObjectAttributes obj_attributes)
 {
     using (var key = NtKey.Create(obj_attributes, Access, Options | KeyCreateOptions.CreateLink, Transaction))
     {
         key.SetSymbolicLinkTarget(Win32Path ? NtKeyUtils.Win32KeyNameToNt(Target) : Target);
         if (PassThru)
         {
             return(key.Duplicate());
         }
         return(null);
     }
 }
Beispiel #19
0
        static NtKey OpenKey(string name)
        {
            if (!name.StartsWith(@"\"))
            {
                name = NtKeyUtils.Win32KeyNameToNt(name);
            }

            using (ObjectAttributes obja = new ObjectAttributes(name,
                                                                AttributeFlags.CaseInsensitive | AttributeFlags.OpenLink, null))
            {
                return(NtKey.Open(obja, KeyAccessRights.MaximumAllowed, 0));
            }
        }
Beispiel #20
0
 private void CheckAccessUnderImpersonation(TokenEntry token, AccessMask access_rights, NtKey key)
 {
     using (ObjectAttributes obj_attributes = new ObjectAttributes(string.Empty,
                                                                   AttributeFlags.CaseInsensitive | AttributeFlags.OpenLink, key))
     {
         using (var result = token.Token.RunUnderImpersonate(() => NtKey.Open(obj_attributes, KeyAccessRights.MaximumAllowed, 0, false)))
         {
             if (result.IsSuccess && IsAccessGranted(result.Result.GrantedAccessMask, access_rights))
             {
                 WriteAccessCheckResult(key.FullPath, key.NtType.Name, result.Result.GrantedAccessMask, key.NtType.GenericMapping,
                                        null, typeof(KeyAccessRights), true, token.Information);
             }
         }
     }
 }
Beispiel #21
0
        private static NtResult <NtKey> OpenKey(string name, NtObject root, bool open_link, bool open_for_backup)
        {
            AttributeFlags flags = AttributeFlags.CaseInsensitive;

            if (open_link)
            {
                flags |= AttributeFlags.OpenLink;
            }

            using (ObjectAttributes obja = new ObjectAttributes(name,
                                                                flags, root))
            {
                return(NtKey.Open(obja, KeyAccessRights.MaximumAllowed, open_for_backup ? KeyCreateOptions.BackupRestore : KeyCreateOptions.NonVolatile, false));
            }
        }
 private protected override void PopulateKeyData(NtKey key)
 {
     base.PopulateKeyData(key);
     try
     {
         if (key.IsAccessGranted(KeyAccessRights.QueryValue))
         {
             _value_dict = key.QueryValues().ToDictionary(v => v.Name, StringComparer.OrdinalIgnoreCase);
         }
     }
     catch
     {
     }
     _class_name           = key.ClassName;
     _control_flags        = key.ControlFlags;
     _virtualization_flags = key.VirtualizationFlags;
 }
Beispiel #23
0
        /// <summary>
        /// Process record.
        /// </summary>
        protected override void ProcessRecord()
        {
            switch (ParameterSetName)
            {
            case "FromKey":
                Key.Delete();
                break;

            case "FromPath":
                using (var obja = GetObjectAttributes())
                {
                    using (var key = NtKey.Open(obja, KeyAccessRights.Delete,
                                                KeyCreateOptions.NonVolatile, Transaction))
                    {
                        key.Delete();
                    }
                }
                break;
            }
        }
        /// <summary>
        /// Overridden method to initialize default drives.
        /// </summary>
        /// <returns>The list of default drives.</returns>
        protected override Collection <PSDriveInfo> InitializeDefaultDrives()
        {
            Collection <PSDriveInfo> drives = new Collection <PSDriveInfo>();

            drives.Add(new PSDriveInfo("NtObject", ProviderInfo, GLOBAL_ROOT, "NT Object Manager Root Directory", null));
            int    session_id = Process.GetCurrentProcess().SessionId;
            string base_dir;

            if (session_id == 0)
            {
                base_dir = GLOBAL_ROOT + "BaseNamedObjects";
            }
            else
            {
                base_dir = $@"{GLOBAL_ROOT}Sessions\{session_id}\BaseNamedObjects";
            }

            drives.Add(new PSDriveInfo("NtObjectSession", ProviderInfo,
                                       base_dir, "Current Session NT Objects", null));

            drives.Add(new PSDriveInfo("NtKey", ProviderInfo,
                                       KEY_ROOT, "Root NT Key Directory", null));

            string user_path = $@"User\{NtProcess.Current.User}";

            using (var key = NtKey.Open($@"\REGISTRY\{user_path}", null, KeyAccessRights.MaximumAllowed, KeyCreateOptions.NonVolatile, null, false))
            {
                if (key.IsSuccess)
                {
                    drives.Add(new PSDriveInfo("NtKeyUser", ProviderInfo,
                                               $@"{KEY_ROOT}{user_path}", "User NT Key Directory", null));
                }
                else
                {
                    drives.Add(new PSDriveInfo("NtKeyUser", ProviderInfo,
                                               $@"{KEY_ROOT}User\.DEFAULT", "User NT Key Directory", null));
                }
            }

            return(drives);
        }
Beispiel #25
0
        static void CheckAccess(NtToken token, NtKey key)
        {
            NtType type = key.NtType;

            if (!key.IsAccessGranted(KeyAccessRights.ReadControl))
            {
                return;
            }

            SecurityDescriptor sd = key.SecurityDescriptor;
            AccessMask         granted_access;

            if (_key_rights != 0)
            {
                granted_access = NtSecurity.GetAllowedAccess(token, type,
                                                             _key_rights, sd.ToByteArray());
            }
            else
            {
                granted_access = NtSecurity.GetMaximumAccess(token, type, sd.ToByteArray());
            }

            if (!granted_access.IsEmpty)
            {
                // As we can get all the rights for the key get maximum
                if (_key_rights != 0)
                {
                    granted_access = NtSecurity.GetMaximumAccess(token, type, sd.ToByteArray());
                }

                if (!_show_write_only || type.HasWritePermission(granted_access))
                {
                    Console.WriteLine("{0} : {1:X08} {2}", key.FullPath, granted_access, AccessMaskToString(granted_access, type));
                    if (_print_sddl)
                    {
                        Console.WriteLine("{0}", sd.ToSddl());
                    }
                }
            }
        }
        static void CheckAccess(NtKey key)
        {
            if (!key.IsAccessGranted(KeyAccessRights.ReadControl))
            {
                return;
            }

            SecurityDescriptor sd = key.SecurityDescriptor;
            uint granted_access = 0;

            if (_key_rights != 0)
            {
                granted_access = NtSecurity.GetAllowedAccess(_token, _type, _key_rights, sd.ToByteArray());
            }
            else
            {
                granted_access = NtSecurity.GetMaximumAccess(_token, _type, sd.ToByteArray());
            }

            if (granted_access != 0)
            {
                // As we can get all the rights for the key get maximum
                if (_key_rights != 0)
                {
                    granted_access = NtSecurity.GetMaximumAccess(_token, _type, sd.ToByteArray());
                }

                if (!_show_write_only || _type.HasWritePermission(granted_access))
                {
                    Console.WriteLine("{0} : {1:X08} {2}", key.FullPath, granted_access, AccessMaskToString(granted_access));
                    if (_print_sddl)
                    {
                        Console.WriteLine("{0}", sd.ToSddl());
                    }
                }
            }
        }
Beispiel #27
0
        private void DumpKey(IEnumerable <TokenEntry> tokens, AccessMask access_rights, bool open_for_backup, NtKey key, int current_depth)
        {
            if (IncludePath(key.Name))
            {
                var sd = GetSecurityDescriptor(key);
                if (sd.IsSuccess)
                {
                    foreach (var token in tokens)
                    {
                        CheckAccess(token, key, access_rights, sd.Result);
                    }
                }
                else
                {
                    // If we can't read security descriptor then try opening the key.
                    foreach (var token in tokens)
                    {
                        CheckAccessUnderImpersonation(token, access_rights, key);
                    }
                }
            }

            if (Stopping || current_depth <= 0)
            {
                return;
            }

            // Can never recurse predefined key handles so just ignore them.
            if (Recurse && key.IsAccessGranted(KeyAccessRights.EnumerateSubKeys) && !key.PredefinedHandle)
            {
                foreach (string subkey in key.QueryKeys())
                {
                    if (FilterPath(subkey))
                    {
                        continue;
                    }
                    using (var result = OpenKey(subkey, key, true, open_for_backup))
                    {
                        if (result.IsSuccess)
                        {
                            DumpKey(tokens, access_rights, open_for_backup, result.Result, current_depth - 1);
                        }
                        else
                        {
                            WriteAccessWarning($@"{key.FullPath}\{subkey}", result.Status);
                        }
                    }
                }
            }
        }
        static void DumpKey(NtKey key)
        {
            string key_name = key.FullPath;
            if (_walked.Contains(key_name))
            {
                return;
            }

            _walked.Add(key_name);

            try
            {
                CheckAccess(key);

                if (_recursive && key.IsAccessGranted(KeyAccessRights.EnumerateSubKeys))
                {
                    using (var keys = key.QueryAccessibleKeys(KeyAccessRights.MaximumAllowed))
                    {
                        foreach (NtKey subkey in keys)
                        {
                            DumpKey(subkey);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine("Error dumping key {0} {1}", key.FullPath, ex.Message);
            }
        }
 /// <summary>
 /// Method to create an object from a set of object attributes.
 /// </summary>
 /// <param name="obj_attributes">The object attributes to create/open from.</param>
 /// <returns>The newly created object.</returns>
 protected override object CreateObject(ObjectAttributes obj_attributes)
 {
     return(NtKey.Open(obj_attributes, Access, Options));
 }
 /// <summary>
 /// Method to create an object from a set of object attributes.
 /// </summary>
 /// <param name="obj_attributes">The object attributes to create/open from.</param>
 /// <returns>Always null.</returns>
 protected override object CreateObject(ObjectAttributes obj_attributes)
 {
     NtKey.UnloadKey(obj_attributes, Flags, true);
     return(null);
 }
 private protected virtual void PopulateKeyData(NtKey key)
 {
     _is_symlink     = key.IsLink;
     _symlink_target = key.GetSymbolicLinkTarget(false).GetResultOrDefault(string.Empty);
 }
Beispiel #32
0
        internal static NtResult <CentralAccessRule> FromRegistry(NtKey key, bool throw_on_error)
        {
            string             name        = string.Empty;
            string             description = string.Empty;
            SecurityDescriptor sd          = null;
            SecurityDescriptor staged_sd   = null;
            string             applies_to  = string.Empty;
            string             change_id   = string.Empty;
            uint flags = 0;

            foreach (var value in key.QueryValues())
            {
                switch (value.Name.ToLower())
                {
                case "appliesto":
                    if (value.Data.Length > 0)
                    {
                        var result = NtSecurity.ConditionalAceToString(value.Data, throw_on_error);
                        if (!result.IsSuccess)
                        {
                            return(result.Cast <CentralAccessRule>());
                        }
                        applies_to = result.Result;
                    }
                    break;

                case "sd":
                {
                    if (value.Data.Length > 0)
                    {
                        var sd_result = SecurityDescriptor.Parse(value.Data, throw_on_error);
                        if (!sd_result.IsSuccess)
                        {
                            return(sd_result.Cast <CentralAccessRule>());
                        }
                        sd = sd_result.Result;
                    }
                }
                break;

                case "stagedsd":
                {
                    if (value.Data.Length > 0)
                    {
                        var sd_result = SecurityDescriptor.Parse(value.Data, throw_on_error);
                        if (!sd_result.IsSuccess)
                        {
                            return(sd_result.Cast <CentralAccessRule>());
                        }
                        staged_sd = sd_result.Result;
                    }
                }
                break;

                case "changeid":
                    change_id = value.ToString().TrimEnd('\0');
                    break;

                case "description":
                    description = value.ToString().TrimEnd('\0');
                    break;

                case "flags":
                    if (value.Type == RegistryValueType.Dword)
                    {
                        flags = (uint)value.ToObject();
                    }
                    break;

                case "name":
                    name = value.ToString().TrimEnd('\0');
                    break;
                }
            }
            return(new CentralAccessRule(name, description, sd, staged_sd, applies_to, change_id, flags).CreateResult());
        }