Anyone have any idea how to get the SACL's on a remote service using C#? I've tried numerous different methods, and basically nothing works. I can get the DACL's and SACL's on the local machine, but getting either on a remote machine doesn't appear to be possible.
What I've done is create a class called ServiceSecurity that inherits from NativeObjectSecurity and acts a lot like the RegistrySecurity class. Below are two of the constructors that I have:
public ServiceSecurity(string serviceName, AccessControlSections includeSections)
: base(true, ResourceType.Service, serviceName, includeSections, null, null)
{
}
public ServiceSecurity(System.Runtime.InteropServices.SafeHandle handle, AccessControlSections includeSections)
: base(true, ResourceType.Service, handle, includeSections)
{
}
The first one uses a service name, while the second expects a handle to the service. Obviously the first one works fine to get the DACL's and SACL's because it's all local, but to get to a remote machine, I'm using the ServiceController class to find the service on the remote machine. After getting it, I pass the ServiceHandle property of the service to the ServiceSecurity class I've built, at which point I get an Unauthorized Access exception, which doesn't seem right because my user account is a Domain Admin for the domain, and a Local admin on the target box. I also have the SeSecurityPrivilege right, which should allow me access.
Anyone have any ideas? It seems like the SafeHandle I'm getting isn't right, but the SafeHandle properties say that it's not closed and that it is a valid handle, so I don't quite know what's going on.
Here's the code I'm using to try to retrieve the data:
ServiceSecurity sSec = new ServiceSecurity(services[i].ServiceName, accessSections); string outputData = sSec.GetSecurityDescriptorSddlForm(accessSections);
The above will work for local permissions and audit settings (DACL's and SACL's). But it's designed to work on a local machine. If I do this instead:
ServiceSecurity sSec = new ServiceSecurity(services[i].ServiceHandle, accessSections); string outputData = sSec.GetSecurityDescriptorSddlForm(accessSections);
The ServiceSecurity constructor fails on both local and remote servers for the SACL's as follows, but still works for the DACL's:
System.UnauthorizedAccessException: Attempted to perform an unauthorized operation. at System.Security.AccessControl.Win32.GetSecurityInfo(ResourceType resourceType, String name, SafeHandle handle, AccessControlSections accessControlSections, RawSecurityDescriptor& resultSd) at System.Security.AccessControl.NativeObjectSecurity.CreateInternal(ResourceType resourceType, Boolean isContainer, String name, SafeHandle handle, AccessControlSections includeSections, Boolean createByName, ExceptionFromErrorCode exceptionFromErrorCode, Object exceptionContext) at System.Security.AccessControl.NativeObjectSecurity..ctor(Boolean isContainer, ResourceType resourceType, SafeHandle handle, AccessControlSections includeSections)
For the accessSections, I am only specifying a single one of the AccessControlSections, be it Audit or Access and Audit seems to fail every time when I'm passing the ServiceHandle.
Update:
So perhaps the question should really be, how do I get a handle to a service that has the ACCESS_SYSTEM_SECURITY
rights so I can get the SACL's?