Adjusting DCOM Settings via Script
I was recently tasked with adjusting the DCOM Security Settings (DCOM: Machine Access Restrictions and DCOM: Machine Launch Restrictions) in the local security policy on a number of computers. These can be changed manually by opening the Local Security Policy and browsing to Local Policies and then Security Options, but it needed to be more automated than that and needed to be rolled out to a few hundred Windows XP Computers.
The requirements of the script were as follows:
- Add two groups to each of the policy settings
- Do not try and add them again if they already exist
- Do not overwrite the users/groups that are already there
- Group Policy is not an option for this project
- Log Everything
I played around for about 45 minutes with secedit and applying a policy that way but I couldn’t get it to import and append the existing policy correctly. I decided that the changes were going to need to be made through script, and probably through the registry.
I first used REGMON (from Microsoft SysInternals) to find out where these settings were stored in the registry. I found they are both in the same spot under HKLM\Software\Policies\Microsoft\Windows NT\DCOM. Unfortunately, it wasn’t just a comma delimited list of users and rights, it looked a bit more like this:

On the bright side, at least it wasn’t some binary key that made even less sense. These strings seemed workable; it seemed like there was a pattern.
I’ll save you the paragraphs I could write about how I added and removed users, changed their permissions, etc. just to see the changes on these keys to break the pattern and just bring you to my end result. The strings are in SDDL (Security Descriptor Definition Language) format. While Microsoft had some light write-ups on MSDN about SDDL, the best resource I found on the matter was at this University of Washington page.
While reading about SDDL from that site is important if you’re looking to take on a similar task, the short version is that SDDL strings can be first broken up into five groups (Header, DACL, SACL, Primary Group, and Owner). Each of these fields is separated by a colon. I wont go into details about each of these as the University of Washington site will do this for you, but for the purposes of this project the only thing that needs to be changed for the DCOM policies is the last field in the string. In my screen shot above, that’s the one that looks like this:
(A;;CCDCLC;;;AN)(A;;CCDCLC;;;WD).
In a nutshell, each user or group in the string is represented by a parentheses grouping. You can see in the one in bold that there are two groupings, representing two users/groups. These grouping are further broken down by fields that are separated by semicolons. You can see there are six fields and they are:
- Type
- Flags
- Permissions
- ObjectType
- Trustee (SID)
Again, read up on either MSDN or the University of Washington page to learn about what each of these fields mean. You can see from the existing SDDL strings that the DCOM policy only uses three of these fields: Type, Permissions, and Trustee. By digesting all of this, I was now ready to create a script to parse the existing users/groups, modify their permissions if necessary, and add the users if they didn’t exist.
The script below is the product of this effort. You are welcome to use, however please keep the header intact and provide credit to this post if you share it with others. I’ve commented on how the script works beneath it, and please don’t forget to read my disclaimer at the bottom of each post!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 | ; ============================================================================================================================================== ; Windows XP Local Security Policy DCOM Permissions Change ; ============================================================================================================================================== ; Script Version: 1.0 ; AutoIt Version: 3.0 ; Language: English ; Author: Chris (www.TechnicallyChris.com) ; Description: Modifies DCOM Security Settings ; 2-Sept-2009: Created First Revision of Script #include <date.au3> ; Setup Logs $logFolder = @TempDir & "\DCOM" $log = $logFolder & "\DCOMModifier.log" If Not FileExists($logFolder) then DirCreate($logFolder) If FileExists($log) then FileWriteLine($log, "") FileWriteLine($log, "[" & _now() & "] Capturing Current DCOM Settings") $Access = RegRead("HKLM\Software\Policies\Microsoft\Windows NT\DCOM", "MachineAccessRestriction") $Launch = RegRead("HKLM\Software\Policies\Microsoft\Windows NT\DCOM", "MachineLaunchRestriction") FileWriteLine($log, "[" & _now() & "] MachineAccessRestriction=" & $access) FileWriteLine($log, "[" & _now() & "] MachineLaunchRestriction=" & $launch) ; MACHINE ACCESS RESTRICTIONS FileWriteLine($log, "[" & _now() & "] Beginning Parse of MachineAccessRestrictions") $SDDL = StringSplit($access,":") FileWriteLine($log, "[" & _now() & "] O = " & $SDDL[1]) FileWriteLine($log, "[" & _now() & "] OWNER_SID = " & $SDDL[2]) FileWriteLine($log, "[" & _now() & "] GROUP_SID = " & $SDDL[3]) FileWriteLine($log, "[" & _now() & "] DACL_FLAGS = " & $SDDL[4]) $newSDDL = $SDDL[1] & ":" & $SDDL[2] & ":" & $SDDL[3] FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) $DACLS = StringSplit($SDDL[4],")") ; Position 0 of array will be found ; Position n (last) of array will be empty because of the way we stringsplit on the end paren $sidANON = False $sidEVERYONE = False For $i = 1 to UBOUND($DACLS)-2 $DACLS[$i] = StringReplace($DACLS[$i], "(", "") FileWriteLine($log, "[" & _now() & "] DACL #" & $i & "=" & $DACLS[$i]) $ACES = StringSplit($DACLS[$i],";") FileWriteLine($log, "[" & _now() & "] ACE TYPE=" & $ACES[1]) FileWriteLine($log, "[" & _now() & "] ACE Flags=" & $ACES[2]) FileWriteLine($log, "[" & _now() & "] ACE Permissions=" & $ACES[3]) FileWriteLine($log, "[" & _now() & "] ACE ObjectType=" & $ACES[4]) FileWriteLine($log, "[" & _now() & "] ACE Inherited ObjectType=" & $ACES[5]) FileWriteLine($log, "[" & _now() & "] ACE Trustee=" & $ACES[6]) if $ACES[6] = "AN" Then FileWriteLine($log, "[" & _now() & "] Trustee is ANONYMOUS, changing permissions to CCDCLC") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(" & $ACES[1] & ";" & $ACES[2] & ";CCDCLC;" & $ACES[4] & ";" & $ACES[5] & ";" & $ACES[6] & ")" $sidANON = true elseif $ACES[6] = "WD" Then FileWriteLine($log, "[" & _now() & "] Trustee is EVERYONE, changing permissions to CCDCLC") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(" & $ACES[1] & ";" & $ACES[2] & ";CCDCLC;" & $ACES[4] & ";" & $ACES[5] & ";" & $ACES[6] & ")" $sidEVERYONE = True else FileWriteLine($log, "[" & _now() & "] Trustee is not on filter list, permissions will be unchanged") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(" & $ACES[1] & ";" & $ACES[2] & ";" & $ACES[3] & ";" & $ACES[4] & ";" & $ACES[5] & ";" & $ACES[6] & ")" endif FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) next If $sidANON = false Then FileWriteLine($log, "[" & _now() & "] Anonymous Trustee not found in SDDL, adding.") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(A;;CCDCLC;;;AN)" FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) EndIf If $sidEVERYONE = false Then FileWriteLine($log, "[" & _now() & "] Everyone Trustee not found in SDDL, adding.") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(A;;CCDCLC;;;WD)" FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) EndIf FileWriteLine($log, "[" & _now() & "] Writing New SID to Registry") RegWrite("HKLM\Software\Policies\Microsoft\Windows NT\DCOM", "MachineAccessRestriction","REG_SZ",$newSDDL) ; LAUNCH ACCESS RESTRICTIONS FileWriteLine($log, "[" & _now() & "] Beginning Parse of MachineLaunchRestrictions") $SDDL = StringSplit($launch,":") FileWriteLine($log, "[" & _now() & "] O = " & $SDDL[1]) FileWriteLine($log, "[" & _now() & "] OWNER_SID = " & $SDDL[2]) FileWriteLine($log, "[" & _now() & "] GROUP_SID = " & $SDDL[3]) FileWriteLine($log, "[" & _now() & "] DACL_FLAGS = " & $SDDL[4]) $newSDDL = $SDDL[1] & ":" & $SDDL[2] & ":" & $SDDL[3] FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) $DACLS = StringSplit($SDDL[4],")") ; Position 0 of array will be found ; Position n (last) of array will be empty because of the way we stringsplit on the end paren $sidADMIN = False $sidEVERYONE = False For $i = 1 to UBOUND($DACLS)-2 $DACLS[$i] = StringReplace($DACLS[$i], "(", "") FileWriteLine($log, "[" & _now() & "] DACL #" & $i & "=" & $DACLS[$i]) $ACES = StringSplit($DACLS[$i],";") FileWriteLine($log, "[" & _now() & "] ACE TYPE=" & $ACES[1]) FileWriteLine($log, "[" & _now() & "] ACE Flags=" & $ACES[2]) FileWriteLine($log, "[" & _now() & "] ACE Permissions=" & $ACES[3]) FileWriteLine($log, "[" & _now() & "] ACE ObjectType=" & $ACES[4]) FileWriteLine($log, "[" & _now() & "] ACE Inherited ObjectType=" & $ACES[5]) FileWriteLine($log, "[" & _now() & "] ACE Trustee=" & $ACES[6]) if $ACES[6] = "BA" Then FileWriteLine($log, "[" & _now() & "] Trustee is ADMINISTRATORS, changing permissions to CCDCLCSWRP") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(" & $ACES[1] & ";" & $ACES[2] & ";CCDCLCSWRP;" & $ACES[4] & ";" & $ACES[5] & ";" & $ACES[6] & ")" $sidADMIN = true elseif $ACES[6] = "WD" Then FileWriteLine($log, "[" & _now() & "] Trustee is EVERYONE, changing permissions to CCDCLCSWRP") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(" & $ACES[1] & ";" & $ACES[2] & ";CCDCLCSWRP;" & $ACES[4] & ";" & $ACES[5] & ";" & $ACES[6] & ")" $sidEVERYONE = True else FileWriteLine($log, "[" & _now() & "] Trustee is not on filter list, permissions will be unchanged") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(" & $ACES[1] & ";" & $ACES[2] & ";" & $ACES[3] & ";" & $ACES[4] & ";" & $ACES[5] & ";" & $ACES[6] & ")" endif FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) next If $sidADMIN = false Then FileWriteLine($log, "[" & _now() & "] Admin Trustee not found in SDDL, adding.") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(A;;CCDCLCSWRP;;;BA)" FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) EndIf If $sidEVERYONE = false Then FileWriteLine($log, "[" & _now() & "] Everyone Trustee not found in SDDL, adding.") if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":" $newSDDL = $newSDDL & "(A;;CCDCLCSWRP;;;WD)" FileWriteLine($log, "[" & _now() & "] New SDDL = " & $newSDDL) EndIf FileWriteLine($log, "[" & _now() & "] Writing New SID to Registry") RegWrite("HKLM\Software\Policies\Microsoft\Windows NT\DCOM", "MachineLaunchRestriction","REG_SZ",$newSDDL) |
Basically, the meat of the script is that after setting up our log file, we read the two registry keys that we need to possibly modify. We then break them down into their 5 parts and log them, and then break the fifth field down into it’s six parts so that we can look at all the users.
We then loop over each user and pull out who the user is and what their permissions are. If they are a user that we want to modify, we update our temporary SDDL string to set the permissions to what we want (see the tables on the University of Washington site). If they are not a user that we care about, we insert them as-is into our temporary SDDL string. If at the end of it all we haven’t found the users we want to modify, we add them. Once all is said and done, we insert the new SDDL right back into the registry.