/// <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)); } }
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); }
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()); }
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); } }
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()); }
/// <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); }
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()); } }
private protected override void PopulateKeyData(NtKey key) { base.PopulateKeyData(key); if (key.IsAccessGranted(KeyAccessRights.QueryValue)) { _values = new List <NtKeyValue>(key.QueryValues()); } }
/// <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); } }
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>()); } }
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; }
/// <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)); }
/// <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)); } }
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); } }
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)); } }
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); } } } }
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; }
/// <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); }
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()); } } } }
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); } } } } }
/// <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); }
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()); }