Archive for January, 2015

Have you ever tried to use PowerShell (or .NET) to mess with file or folder permissions and wondered what the ‘Synchronize’ right means? It pops up all over the place, like on existing ACEs:

And on new ACEs that you create (even if you don’t include it):


If you try to check permissions using the ACL Editor, you won’t see it anywhere. Here’s the ACE for ‘Users’ from the ‘C:\powershell’ folder shown in the first screenshot above:


So, what is this mysterious right, and why does PowerShell/.NET insist on showing it everywhere? Let’s start with the definition from MSDN:

The right to use the object for synchronization. This enables a thread to wait until the object is in the signaled state. Some object types do not support this access right.

The first time I read that, I didn’t think it sounded all that important. It turns out, though, that it’s critical for working with files and folders.

Before I explain a little bit more about why that right shows up, let’s briefly cover what makes up an access control entry’s access mask. It’s a 32-bit integer, which means that, theoretically, there are 32 different rights that can be controlled (32 bits means 32 different on/off switches). In practice, you don’t get that many rights, though. No matter what type of object you’re working with (file, folder, registry key, printer, service, AD object, etc), those 32-bits are broken down like this:

  • Bits 0-15 are used for object specific rights. These rights differ between object types, e.g., bit 1 for a file means ‘CreateFiles’, for a registry key means ‘SetValue’, and for an AD object means ‘DeleteChild’.
  • Bits 16-23 are used for “Standard access rights”. These rights are shared among the different types of securable objects, e.g., bit 16 corresponds to the right to delete the object, and it means the same thing for files, folders, registry keys, etc. As far as I know, only bits 16-20 in this range do anything.
  • Bit 24 controls access to the SACL.
  • Bits 25-27 are reserved and not currently used.
  • Bits 28-31 are “Generic access rights”. They are a shorthand way of specifying four common access masks: read, write, execute, and all (full control). These bits are translated into a combination of object specific and standard access rights, and the translation differs depending on the type of object the ACE belongs to.

The ‘Synchronize’ right is controlled by bit 20, so it’s one of the standard access rights:

PS> [math]::Log([System.Security.AccessControl.FileSystemRights]::Synchronize, 2)

If you manage to remove the right (or if you explicitly deny it), bad things will happen. For folders, you won’t be able to see child items. For files, you won’t be able to view the contents. It turns out some very important Win32 APIs require that right to be granted, at least for file and folder objects. You get a hint of it from this MSDN page:

Note that you cannot use an access-denied ACE to deny only GENERIC_READ or only GENERIC_WRITE access to a file. This is because for file objects, the generic mappings for both GENERIC_READ or GENERIC_WRITE include the SYNCHRONIZE access right. If an ACE denies GENERIC_WRITE access to a trustee, and the trustee requests GENERIC_READ access, the request will fail because the request implicitly includes SYNCHRONIZE access which is implicitly denied by the ACE, and vice versa. Instead of using access-denied ACEs, use access-allowed ACEs to explicitly allow the permitted access rights.

I couldn’t do a good job of translating the actual definition of ‘Synchronize’ earlier, but I think I can translate this paragraph. It’s saying that you can’t create an access denied ACE for just GENERIC_READ or just GENERIC_WRITE as they are defined, because each of those sets of rights include ‘Synchronize’, and you’d effectively be denying both sets of rights. GENERIC_READ (bit 31) and GENERIC_WRITE (bit 30) are two of the four “Generic access rights” mentioned above. When they’re translated/mapped to their object-specific rights, they make up a combination of bits 0-20 of the access mask (object specific and standard rights).

Once translated, GENERIC_READ is very similar to [FileSystemRights]::Read, and GENERIC_WRITE is very similar to [FileSystemRights]::Write. From the same MSDN page, here’s a list of the object specific and standard rights that make up the generic rights (the [FileSystemRights] equivalents are listed in parenthesis):

    • FILE_READ_ATTRIBUTES (ReadAttributes)
    • FILE_READ_DATA (ReadData)
    • FILE_READ_EA (ReadExtendedAttributes)
    • STANDARD_RIGHTS_READ (ReadPermissions)
    • SYNCHRONIZE (Synchronize)
    • FILE_APPEND_DATA (AppendData)
    • FILE_WRITE_ATTRIBUTES (WriteAttributes)
    • FILE_WRITE_DATA (WriteData)
    • FILE_WRITE_EA (WriteExtendedAttributes)
    • STANDARD_RIGHTS_WRITE (ReadPermissions)
    • SYNCHRONIZE (Synchronize)

The [FileSystemRights] enumeration has values for Read and Write that almost match what is defined above. Since PowerShell coerces strings into enumerations, and enumerations will attempt to show you combined flags where possible, let’s take a look at how those rights are seen when they’re cast as a FileSystemRights enumeration:


Hopefully that makes sense. It’s showing that GENERIC_READ in [FileSystemRights] translates to ‘Read, Synchronize’, which means that GENERIC_READ is not the same as [FileSystemRights]::Read since ‘Read’ doesn’t include ‘Synchronize’. GENERIC_WRITE and [FileSystemRights]::Write are almost the same, except [FileSystemRights]::Write is also missing ‘ReadPermissions’ in addition to ‘Synchronize’.

So, why don’t the generic rights translate to the same numeric values for [FileSystemRights]? It goes back to the warning from the MSDN page above: if you want to deny ‘Read’ or ‘Write’ only, you have to remove the ‘Synchronize’ right first. The ACL editor does this, and it doesn’t give you any control over the ‘Synchronize’ right: if you create a new ACE it will determine whether or not the right is added, and it never shows it to you. The creators of the file/folder access control .NET classes didn’t get that luxury. Each ACE has a numeric access mask, and that access mask needs to be translated with a flags enumeration. If the ‘Synchronize’ bit is set, then the flags enumeration string is going to show it, and vice versa. So, they did the next best thing: they pulled ‘Synchronize’ from the combined ‘Read’ and ‘Write’ rights in the [FileSystemRights] enumeration, and made sure that creating a new allow ACE or audit rule automatically adds the ‘Synchronize’ right, and creating a new deny ACE removes it. If an application wants to hide the ‘Synchronize’ right from the end user, that’s fine, but the underlying .NET object will show it if it’s present.

I hope that makes sense and clears that up. If not, please leave a comment where something needs to be explained a little better, and I’ll try to expand on it some more.

Happy New Year! It’s been a while since I’ve posted anything on here, but I’ve still been working on the module. I posted a preview of version 4.0 of my access control module on the TechNet Script Repository. It only has three commands right now and can only view security descriptors, but I think it’s a huge improvement over version 3.0. Some of the biggest changes are listed below:


The most noticeable difference between versions 3 and 4 has to be the speed improvement. Version 3.0 added Active Directory support, and that extra functionality really highlighted just how slow the module had become. Version 4.0 is compiled C# code (it’s actually my first C# project). Check out the speed difference:


I cut the command off, but it was just calling Get-SecurityDescriptor and Get-Acl against ‘C:\Windows’ 20 times and using Measure-Command and Measure-Object to get the average time. As you can see, Get-SecurityDescriptor is as fast (and sometimes faster) than the native Get-Acl cmdlet (this was by no means a rigorous test, so I won’t say it’s always faster than the native cmdlet).

Better Long Path Support/Inline Path Options

Version 3.0 supported using paths longer than 255 characters, but just barely. You either had to know the full path or the depth in a folder structure of the file or folder you were after. For example, you could pass ‘c:\longpathliveshere\*\*\*’ as a path to the functions, and it would resolve to any files or folders that were 3 levels deeper than ‘C:\longpathliveshere’, no matter how long the resulting paths were (this worked by proxying the Resolve-Path cmdlet inside the module scope and using the Microsoft.Experimental.IO.LongPathDirectory class to handle any paths that were too long). You couldn’t use it to recurse through a folder that had paths that were too long, though.

Version 4.0 will take care of that, even though I’m not 100% sure how yet. Right now, there’s a cmdlet called Get-PacPathInfo that takes any object and attempts to get the necessary information from it to get a security descriptor. The cmdlet has -Recurse, -Directory, and -File switches that allow you to, where appropriate, recurse through a structure and filter just on files and/or folders. So if you feed it a service object and use any of those switches, they’re going to be ignored. -Recurse will work on registry key and folder objects, though.

You can take the output from that cmdlet and pipe it into Get-SecurityDescriptor or Get-AccessControlEntry. I’m not sure that I’ll leave that cmdlet in the module, though, because that same functionality can be achieved through inline path options. Right now, the syntax for those is very similar to inline regex options:


Right now there are four inline options: l for literal path, r for recurse, d for directory, and f for file.

Display Options

This is something else that’s definitely not in its final form. I’ve been playing around with displaying ACEs differently on the fly. If you use Get-AccessControlEntry, you’ll find a -DisplayOptions parameter that gives you lots of different switches to try that will change how the ACEs are shown. Try each of these yourself and see if you can spot the differences:

PS> Get-AccessControlEntry C:\Windows
PS> Get-AccessControlEntry C:\Windows -DisplayOptions DontMergeAces
PS> Get-AccessControlEntry C:\Windows -DisplayOptions DontMergeAces, DontMapGenericRights
PS> Get-AccessControlEntry C:\Windows -DisplayOptions ShowDetailedRights

Backup Mode

Have you ever encountered a file, folder, or registry key that you didn’t have access to as an administrator? If you wanted to view/use the object, or even to view the DACL or SACL, you had to take ownership of the object first. Well, now you can view the security descriptor’s contents without having to take ownership (assuming you have the SeBackupPrivilege assigned):


You can try it yourself. It works on files, folders, and registry keys right now. If you don’t have a file or folder that is denying you access as an administrator lying around, you can do the following:

1. Create a file, folder, or registry key
2. Make sure it has some ACEs, either inherited or explicitly defined
3. Add an ACE that denies ‘Full Control’ to your user
4. Make sure to set another user as the owner

To test, make sure you can’t open the folder. Then try Get-SecurityDescriptor with the -BypassAclCheck switch and take a look.

Oh, here’s a semi-unrelated trick that should work with the new path system if you’ve got access to a remote computer (I’m already planning to one day put this into a PS provider that also includes the ability to filter on value names and data, unless someone else beats me to it):

PS> Get-SecurityDescriptor \\computername\hklm:\software\*
Friendly AppliesTo

One area where I really like using my module over the native .NET access control classes is showing what exactly an ACE applies to. For non-containers, i.e., files, services, printers, etc, that’s easy since it only applies to the object itself. Folders, though, can have ACEs that apply to themselves, their sub folders, and their files. Registry keys and WMI namespaces can have ACEs that apply to themselves and/or any child containers. We’re not going to cover AD objects right now, but they have different ways that ACEs can be applied. The .NET classes relay this information through the InheritanceFlags and PropagationFlags properties of an ACE. The PAC module relays it through the AppliesTo property (before version 4.0, there was also an OnlyAppliesHere property, but that’s now contained in AppliesTo as well). When you’re looking at the default table formatting of an object’s ACEs, AppliesTo is shown in an abbreviated form:

In version 3.0, the list view would spell those letters out in the generic Object, ChildContainer, ChildObjects form. Version 4.0 actually shows you object specific names, though. Here’s Get-AccessControlEntry’s output being sent to Select-Object showing the short and long forms of the AppliesTo property in table form:


If you like, you can try it out on a registry key and see what it looks like.

I personally like the abbreviated view better in the table format, but others may like the longer version in that view. This is an area where I’m still trying to figure out how I’d like to give the user the ability to change the view, either temporarily or permanently.

There are lots of other small things, too. For instance, try using Export-Csv with both version 3.0 and version 4.0. The new version is much cleaner because it’s using a custom class instead of adding properties to an existing .NET class.

Obviously this is still very early and is missing a ton of functionality: there are no modification commands, DSC, or effective access (which was another one of my favorite 3.0 features). Anything you see is subject to change (I can guarantee that the backing enumeration for the -Sections parameter on Get-SecurityDescriptor is going to have some changes, and the -Audit switch will somehow make a return to that command, too).  And the source code isn’t posted yet (you can decompile it, though). All of that is coming. The effective access stuff is pretty much the only part I haven’t started working on in C# yet, but all of the hard work was done almost a year ago when working on version 3.0. I can’t wait to see the speed improvements in that area.

In the meantime, please try this out and let me know what you think. If you find any bugs, or if you have any suggestions for ways to make it better, please let me know. You can post a comment here, on the Q&A page of the module’s repository page, or send me an email at magicrohn -at-