Adjusting DCOM Settings via Script
This post was previously released under a different blog and is being republished by me below. That site is no longer available. I am the original author.
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.
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.
1; ==============================================================================================================================================
2; Windows XP Local Security Policy DCOM Permissions Change
3; ==============================================================================================================================================
4
5; Script Version: 1.0
6; AutoIt Version: 3.0
7; Language: English
8; Description: Modifies DCOM Security Settings
9
10; 2-Sept-2009: Created First Revision of Script
11
12#include
13
14; Setup Logs
15$logFolder = @TempDir & "\\DCOM"
16$log = $logFolder & "\\DCOMModifier.log"
17
18If Not FileExists($logFolder) then DirCreate($logFolder)
19
20If FileExists($log) then FileWriteLine($log, "")
21
22FileWriteLine($log, "\[" & \_now() & "\] Capturing Current DCOM Settings")
23$Access = RegRead("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineAccessRestriction")
24$Launch = RegRead("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineLaunchRestriction")
25
26FileWriteLine($log, "\[" & \_now() & "\] MachineAccessRestriction=" & $access)
27FileWriteLine($log, "\[" & \_now() & "\] MachineLaunchRestriction=" & $launch)
28
29; MACHINE ACCESS RESTRICTIONS
30FileWriteLine($log, "\[" & \_now() & "\] Beginning Parse of MachineAccessRestrictions")
31
32$SDDL = StringSplit($access,":")
33
34FileWriteLine($log, "\[" & \_now() & "\] O = " & $SDDL\[1\])
35FileWriteLine($log, "\[" & \_now() & "\] OWNER\_SID = " & $SDDL\[2\])
36FileWriteLine($log, "\[" & \_now() & "\] GROUP\_SID = " & $SDDL\[3\])
37FileWriteLine($log, "\[" & \_now() & "\] DACL\_FLAGS = " & $SDDL\[4\])
38
39$newSDDL = $SDDL\[1\] & ":" & $SDDL\[2\] & ":" & $SDDL\[3\]
40FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
41
42$DACLS = StringSplit($SDDL\[4\],")")
43
44; Position 0 of array will be found
45; Position n (last) of array will be empty because of the way we stringsplit on the end paren
46
47$sidANON = False
48$sidEVERYONE = False
49
50For $i = 1 to UBOUND($DACLS)-2
51 $DACLS\[$i\] = StringReplace($DACLS\[$i\], "(", "")
52 FileWriteLine($log, "\[" & \_now() & "\] DACL #" & $i & "=" & $DACLS\[$i\])
53 $ACES = StringSplit($DACLS\[$i\],";")
54 FileWriteLine($log, "\[" & \_now() & "\] ACE TYPE=" & $ACES\[1\])
55 FileWriteLine($log, "\[" & \_now() & "\] ACE Flags=" & $ACES\[2\])
56 FileWriteLine($log, "\[" & \_now() & "\] ACE Permissions=" & $ACES\[3\])
57 FileWriteLine($log, "\[" & \_now() & "\] ACE ObjectType=" & $ACES\[4\])
58 FileWriteLine($log, "\[" & \_now() & "\] ACE Inherited ObjectType=" & $ACES\[5\])
59 FileWriteLine($log, "\[" & \_now() & "\] ACE Trustee=" & $ACES\[6\])
60 if $ACES\[6\] = "AN" Then
61 FileWriteLine($log, "\[" & \_now() & "\] Trustee is ANONYMOUS, changing permissions to CCDCLC")
62 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
63 $newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLC;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
64 $sidANON = true
65 elseif $ACES\[6\] = "WD" Then
66 FileWriteLine($log, "\[" & \_now() & "\] Trustee is EVERYONE, changing permissions to CCDCLC")
67 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
68 $newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLC;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
69 $sidEVERYONE = True
70 else
71 FileWriteLine($log, "\[" & \_now() & "\] Trustee is not on filter list, permissions will be unchanged")
72 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
73 $newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";" & $ACES\[3\] & ";" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
74 endif
75 FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
76next
77
78If $sidANON = false Then
79 FileWriteLine($log, "\[" & \_now() & "\] Anonymous Trustee not found in SDDL, adding.")
80 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
81 $newSDDL = $newSDDL & "(A;;CCDCLC;;;AN)"
82 FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
83EndIf
84If $sidEVERYONE = false Then
85 FileWriteLine($log, "\[" & \_now() & "\] Everyone Trustee not found in SDDL, adding.")
86 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
87 $newSDDL = $newSDDL & "(A;;CCDCLC;;;WD)"
88 FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
89EndIf
90
91FileWriteLine($log, "\[" & \_now() & "\] Writing New SID to Registry")
92RegWrite("HKLM\\Software\\Policies\\Microsoft\\Windows NT\\DCOM", "MachineAccessRestriction","REG\_SZ",$newSDDL)
93
94; LAUNCH ACCESS RESTRICTIONS
95FileWriteLine($log, "\[" & \_now() & "\] Beginning Parse of MachineLaunchRestrictions")
96
97$SDDL = StringSplit($launch,":")
98
99FileWriteLine($log, "\[" & \_now() & "\] O = " & $SDDL\[1\])
100FileWriteLine($log, "\[" & \_now() & "\] OWNER\_SID = " & $SDDL\[2\])
101FileWriteLine($log, "\[" & \_now() & "\] GROUP\_SID = " & $SDDL\[3\])
102FileWriteLine($log, "\[" & \_now() & "\] DACL\_FLAGS = " & $SDDL\[4\])
103
104$newSDDL = $SDDL\[1\] & ":" & $SDDL\[2\] & ":" & $SDDL\[3\]
105FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
106
107$DACLS = StringSplit($SDDL\[4\],")")
108
109; Position 0 of array will be found
110; Position n (last) of array will be empty because of the way we stringsplit on the end paren
111
112$sidADMIN = False
113$sidEVERYONE = False
114
115For $i = 1 to UBOUND($DACLS)-2
116 $DACLS\[$i\] = StringReplace($DACLS\[$i\], "(", "")
117 FileWriteLine($log, "\[" & \_now() & "\] DACL #" & $i & "=" & $DACLS\[$i\])
118 $ACES = StringSplit($DACLS\[$i\],";")
119 FileWriteLine($log, "\[" & \_now() & "\] ACE TYPE=" & $ACES\[1\])
120 FileWriteLine($log, "\[" & \_now() & "\] ACE Flags=" & $ACES\[2\])
121 FileWriteLine($log, "\[" & \_now() & "\] ACE Permissions=" & $ACES\[3\])
122 FileWriteLine($log, "\[" & \_now() & "\] ACE ObjectType=" & $ACES\[4\])
123 FileWriteLine($log, "\[" & \_now() & "\] ACE Inherited ObjectType=" & $ACES\[5\])
124 FileWriteLine($log, "\[" & \_now() & "\] ACE Trustee=" & $ACES\[6\])
125 if $ACES\[6\] = "BA" Then
126 FileWriteLine($log, "\[" & \_now() & "\] Trustee is ADMINISTRATORS, changing permissions to CCDCLCSWRP")
127 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
128 $newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLCSWRP;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
129 $sidADMIN = true
130 elseif $ACES\[6\] = "WD" Then
131 FileWriteLine($log, "\[" & \_now() & "\] Trustee is EVERYONE, changing permissions to CCDCLCSWRP")
132 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
133 $newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";CCDCLCSWRP;" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
134 $sidEVERYONE = True
135 else
136 FileWriteLine($log, "\[" & \_now() & "\] Trustee is not on filter list, permissions will be unchanged")
137 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
138 $newSDDL = $newSDDL & "(" & $ACES\[1\] & ";" & $ACES\[2\] & ";" & $ACES\[3\] & ";" & $ACES\[4\] & ";" & $ACES\[5\] & ";" & $ACES\[6\] & ")"
139 endif
140 FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
141next
142
143If $sidADMIN = false Then
144 FileWriteLine($log, "\[" & \_now() & "\] Admin Trustee not found in SDDL, adding.")
145 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
146 $newSDDL = $newSDDL & "(A;;CCDCLCSWRP;;;BA)"
147 FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
148EndIf
149If $sidEVERYONE = false Then
150 FileWriteLine($log, "\[" & \_now() & "\] Everyone Trustee not found in SDDL, adding.")
151 if StringRight($newSDDL,1) <> ")" Then $newSDDL = $newSDDL & ":"
152 $newSDDL = $newSDDL & "(A;;CCDCLCSWRP;;;WD)"
153 FileWriteLine($log, "\[" & \_now() & "\] New SDDL = " & $newSDDL)
154EndIf
155
156FileWriteLine($log, "\[" & \_now() & "\] Writing New SID to Registry")
157RegWrite("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.
No comments